From 645abff6f1225312cbe3f71f094e53dd065269d2 Mon Sep 17 00:00:00 2001 From: surechen Date: Tue, 10 Oct 2023 17:06:04 +0800 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 84d44dd1d8ec1e98fff94272ba4f96b2a1f044ca Merge: fa6d1e75125 d23dc2093c2 Author: bors Date: Tue Oct 10 06:04:08 2023 +0000 Auto merge of #116366 - estebank:issue-103982, r=oli-obk Suggest labeling block if `break` is in bare block Fix #103982. commit fa6d1e75125d9c94c21a58c2301492026031fcb8 Merge: 59edd670569 14d29be03c5 Author: bors Date: Tue Oct 10 00:08:23 2023 +0000 Auto merge of #109882 - ecnelises:aix_std, r=workingjubilee Support AIX in Rust standard library Also containing original contributions from `@bzEq` . commit d23dc2093c2037a3f401d917ddb9e9c8507ef116 Author: Esteban Küber Date: Mon Oct 9 22:48:10 2023 +0000 Account for macros commit 59edd67056919c83c59001a8b4f2d8749359377a Merge: cdddcd3bea3 592163fb71a Author: bors Date: Mon Oct 9 21:03:41 2023 +0000 Auto merge of #116497 - compiler-errors:impl-span, r=cjgillot Extend `impl`'s `def_span` to include its where clauses Typically, we highlight the def-span of an impl in a diagnostic due to either: 1. coherence error 2. trait evaluation cycle 3. invalid implementation of built-in trait I find that an impl's where clauses are very often required to understanding why these errors come about, which is unfortunate since where clauses may be located on different lines and don't show up in the error. This PR expands the def-span of impls to include these where clauses. r? cjgillot since you've touched this code a while back to make some spans shorter, but you can also reassign to wg-diagnostics or compiler if you're busy or have no strong opinions. commit c30d57bb77535f3923cbfa666e84d1916b6bce37 Author: Esteban Küber Date: Wed Oct 4 01:29:45 2023 +0000 fix commit 5c17b8be61b69be6c38619f829ba81c64212110d Author: Esteban Küber Date: Tue Oct 3 21:34:52 2023 +0000 Move some tests around commit daac0114591777f29e2f6396e8c2bd5d2c506788 Author: Esteban Küber Date: Tue Oct 3 00:20:59 2023 +0000 Suggest labeling block if `break` is in bare block Fix #103982. commit cdddcd3bea35049dab56888d4391cb9b5b1b4491 Merge: 317783ad2c1 89d610cd06f Author: bors Date: Mon Oct 9 17:14:17 2023 +0000 Auto merge of #116532 - onur-ozkan:enable-rustflags-bootstrap-on-bootstrap, r=albertlarsan68 Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation Adds `RUSTFLAGS_BOOTSTRAP` to `RUSTFLAGS` for bootstrap compilation when `RUSTFLAGS_BOOTSTRAP` exists in the environment. With this PR, `RUSTFLAGS_BOOTSTRAP` will affect every build(as we already do for rustc and std) compiled with stage0 compiler. Resolves #94234 commit 317783ad2c128037ab1ab7722fa3fa61a9e481a5 Merge: be581d9f82a 27a5146e7cd Author: bors Date: Mon Oct 9 15:08:28 2023 +0000 Auto merge of #116569 - matthiaskrgr:rollup-ni0jdd6, r=matthiaskrgr Rollup of 6 pull requests Successful merges: - #115882 (improve the suggestion of `generic_bound_failure`) - #116537 (Fix suggestion span involving wrongly placed generic arg on variant) - #116543 (In smir `find_crates` returns `Vec` instead of `Option`) - #116549 (Simplify some mir passes by using let chains) - #116556 (Sync rustc_codegen_cranelift) - #116561 (Add a test for fixed ICE) r? `@ghost` `@rustbot` modify labels: rollup commit 27a5146e7cd669cd9979865c04929de10fd7b7b3 Merge: ea5cac02e89 2e000ebaa59 Author: Matthias Krüger Date: Mon Oct 9 16:26:03 2023 +0200 Rollup merge of #116561 - ouz-a:testfor_115517, r=compiler-errors Add a test for fixed ICE Addresses https://github.com/rust-lang/rust/issues/115517#issuecomment-1730164116 Closes #115517 r? ``@compiler-errors`` commit ea5cac02e8921e4e3aeb1830b68b88adc3898b27 Merge: 148f5c1bdf9 3ed37652593 Author: Matthias Krüger Date: Mon Oct 9 16:26:02 2023 +0200 Rollup merge of #116556 - bjorn3:sync_cg_clif-2023-10-09, r=bjorn3 Sync rustc_codegen_cranelift The highlights this time are improved simd and inline asm support, `is_x86_feature_detected!()` returning the actual cpu features when inline asm support is enabled and a couple of bug fixes. r? ```@ghost``` ```@rustbot``` label +A-codegen +A-cranelift +T-compiler +subtree-sync commit 148f5c1bdf974e7fc9504aef156016a4852e2053 Merge: 2266e794212 47ebffabb81 Author: Matthias Krüger Date: Mon Oct 9 16:26:02 2023 +0200 Rollup merge of #116549 - DaniPopes:miropts-let-chains, r=oli-obk Simplify some mir passes by using let chains commit 2266e79421279c63e7a6d5b92efe4800940012f9 Merge: 374c885f4a2 4ff6e87a8cb Author: Matthias Krüger Date: Mon Oct 9 16:26:01 2023 +0200 Rollup merge of #116543 - ouz-a:crate_return_vec, r=oli-obk In smir `find_crates` returns `Vec` instead of `Option` Addresses https://github.com/rust-lang/project-stable-mir/issues/40 r? `@oli-obk` commit 374c885f4a29aaf391c5d5eaa1d4c01164725333 Merge: 389747c41dc 23a3b9e4492 Author: Matthias Krüger Date: Mon Oct 9 16:26:01 2023 +0200 Rollup merge of #116537 - gurry:116473-ice-sugg-overlap, r=compiler-errors Fix suggestion span involving wrongly placed generic arg on variant Fixes #116473 The span computation was wrong. It went from the end of the variant to the end of the (wrongly placed) args. However, the variant lived in a different expansion and this resulted in a nonsensical span that overlaps with another and thereby leads to the ICE. In the fix I've changed span computation to not be based on the location of the variant, but purely on the location of the args. I simply extend the start of the args span 2 positions to the left and that includes the `::` and that's all we need apparently. This approach produces a correct span regardless of which macro/expansion the args reside in and where the variant is. commit 389747c41dc81a23088d8aa27425923d7d81f70c Merge: 7ed044c075f a8830631b94 Author: Matthias Krüger Date: Mon Oct 9 16:26:00 2023 +0200 Rollup merge of #115882 - aliemjay:diag-name-region-1, r=compiler-errors improve the suggestion of `generic_bound_failure` - Fixes #115375 - suggest the bound in the correct scope: trait or impl header vs assoc item. See `tests/ui/suggestions/lifetimes/type-param-bound-scope.rs` - don't suggest a lifetime name that conflicts with the other late-bound regions of the function: ```rust type Inv<'a> = *mut &'a (); fn check_bound<'a, T: 'a>(_: T, _: Inv<'a>) {} fn test<'a, T>(_: &'a str, t: T, lt: Inv<'_>) { // suggests a new name `'a` check_bound(t, lt); //~ ERROR } ``` commit be581d9f82a1bcc547c685d7e1b411c246b0bb00 Merge: 7ed044c075f 1210aac1c00 Author: bors Date: Mon Oct 9 13:18:47 2023 +0000 Auto merge of #116142 - GuillaumeGomez:enum-variant-display, r=fmease [rustdoc] Show enum discrimant if it is a C-like variant Fixes https://github.com/rust-lang/rust/issues/101337. We currently display values for associated constant items in traits: ![image](https://github.com/rust-lang/rust/assets/3050060/03e566ec-c670-47b4-8ca2-b982baa7a0f4) And we also display constant values like [here](file:///home/imperio/rust/rust/build/x86_64-unknown-linux-gnu/doc/std/f32/consts/constant.E.html). I think that for coherency, we should display values of C-like enum variants. With this change, it looks like this: ![image](https://github.com/rust-lang/rust/assets/3050060/b53fbbe0-bdb1-4289-8537-f2dd4988e9ac) As for the display of the constant value itself, I used what we already have to keep coherency. We display the C-like variants value in the following scenario: 1. It is a C-like variant with a value set => all the time 2. It is a C-like variant without a value set: All other variants are C-like variants and at least one them has its value set. Here is the result in code: ```rust // Ax and Bx value will be displayed. enum A { Ax = 12, Bx, } // Ax and Bx value will not be displayed enum B { Ax, Bx, } // Bx value will not be displayed enum C { Ax(u32), Bx, } // Bx value will not be displayed, Cx value will be displayed. #[repr(u32)] enum D { Ax(u32), Bx, Cx = 12, } ``` r? `@notriddle` commit 1210aac1c00d9d3435ba801e0dee2d4ac502a738 Author: Guillaume Gomez Date: Mon Oct 9 14:33:04 2023 +0200 Add more complex test cases for enum discriminant display commit 4b6fc8b70fd355614bad31d4268993dc7ef17431 Author: Guillaume Gomez Date: Mon Oct 9 14:26:52 2023 +0200 Improve code commit 592163fb71a07383141a882d185d80b874490982 Author: Michael Goulet Date: Fri Oct 6 20:35:52 2023 +0000 Extend impl's def_span to include where clauses commit 2e000ebaa59851b0be911f016375b20c3b5288c0 Author: Oğuz Ağcayazı Date: Mon Oct 9 13:30:21 2023 +0300 add test commit 7ed044c075fc0e7ad2574d3144ca00ba14608d8f Merge: 093b9d5b295 31cb61b3117 Author: bors Date: Mon Oct 9 09:43:10 2023 +0000 Auto merge of #115238 - workingjubilee:ich-entferne-welke-blumen, r=nikic Formally demote tier 2 MIPS targets to tier 3 Per https://github.com/rust-lang/compiler-team/issues/648 Fixes https://github.com/rust-lang/rust/issues/115218 commit 3ed37652593c188734b226dcecf920cee019961b Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 9 09:04:52 2023 +0000 Remove no longer used dependency from the list of allowed dependencies commit 169055f2ffef79b453e0d89599d0f0c5dabc0adb Merge: 093b9d5b295 81dc066758e Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 9 08:52:46 2023 +0000 Merge commit '81dc066758ec150b43822d4a0c84aae20fe10f40' into sync_cg_clif-2023-10-09 commit 81dc066758ec150b43822d4a0c84aae20fe10f40 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 9 08:33:47 2023 +0000 Rustup to rustc 1.75.0-nightly (bf9a1c8a1 2023-10-08) commit 88198c70e4f0eaf06231122a15d6c967ae0b6159 Merge: cc5db2c1c84 fea943debfa Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 9 08:26:09 2023 +0000 Sync from rust bf9a1c8a193fc373897196321215794c8bebbeec commit 4ff6e87a8cb0d5cba020917bc30ea0f7ef5d2a5b Author: Oğuz Ağcayazı Date: Sun Oct 8 22:55:16 2023 +0300 return crates instead of a crate commit 14d29be03c58587ef4bc7b3d2e1e1e29f2be5985 Author: Qiu Chaofan Date: Mon Apr 3 12:33:51 2023 +0800 Support AIX in Rust standard library commit 093b9d5b295d85e144d0ee7da65ea03987214c06 Merge: 1f48cbc3f8d 005ec2e51ce Author: bors Date: Mon Oct 9 06:00:23 2023 +0000 Auto merge of #116533 - cjgillot:skip-trivial-mir, r=oli-obk Do not run optimizations on trivial MIR. Fixes https://github.com/rust-lang/rust/issues/116513 The bug was introduced in https://github.com/rust-lang/rust/pull/110728, which put the check too early in the query chain. cc `@oli-obk` `@ouz-a` commit 47ebffabb81e80bb3ad3992af1fbb4035e362d77 Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon Oct 9 05:22:31 2023 +0200 Simplify some mir passes by using let chains commit 23a3b9e44926aa0d4c49a722654ef59f010b55ba Author: Gurinder Singh Date: Mon Oct 9 08:04:00 2023 +0530 Fix suggestion span involving wrongly placed generic arg on enum variants When the variant and the (wrongly placed) args are at separate source locations such as being in different macos or one in a macro and the other somwhere outside of it, the arg spans we computed spanned the entire distance between such locations and were hence invalid. . commit 1f48cbc3f8dbd393a7e713a0f90d7c6ec72d58ee Merge: 37fda989ea8 9d211b044d3 Author: bors Date: Mon Oct 9 02:08:13 2023 +0000 Auto merge of #116096 - cjgillot:debuginfo-fndef-size, r=nikic Make FnDef 1-ZST in LLVM debuginfo. Discussed in https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm/topic/LLVM.20HEAD.20llvm.2Edbg.2Edeclare.2Falloca.20size.20mismatch r? `@nikic` commit 37fda989ea8acb1db02748b8478c64e51a515bbd Merge: bf9a1c8a193 ad8271dd56b Author: bors Date: Mon Oct 9 00:03:52 2023 +0000 Auto merge of #116468 - nnethercote:rustc_serialize, r=Mark-Simulacrum Streamline `rustc_serialize` r? `@Mark-Simulacrum` commit 31cb61b3117ca2a9957c19821e020d1d8c8534c7 Author: Jubilee Young Date: Sun Oct 8 15:35:07 2023 -0700 Drop all MIPS targets from CI commit 14cdb3808dadcf9ee57f29d49a0d86c7bb545c91 Author: Jubilee Young Date: Fri Aug 25 21:08:52 2023 -0700 Drop mips*-unknown-linux-musl* to tier 3 Also be more pedantic about spelling: - LE? Is it "less than or equal to"? Say "little endian". - We're Rust, not C, preserve the initial capital in "N64". - "MUSL" doesn't stand for anything; Rich Felker spells it "musl". commit 03870154f4badc1939f718ac74c49438ce507241 Author: Jubilee Young Date: Sun Jul 2 20:59:31 2023 -0700 Drop mips*-unknown-linux-gnu* to tier 3 In the process, be more pedantic about spelling: - LE? Do you mean "limited edition"? It's "little endian". - The name of the ABI is "N64" as in "Nintendo 64". commit 9d211b044d3198f8e2c9a3e5678fafd2a61a5308 Author: Camille GILLOT Date: Sun Oct 8 16:43:57 2023 +0000 Ignore MSVC in test. commit 098fc9715e0f0cc3aa5c6ff0512e389c24d09254 Author: Camille GILLOT Date: Mon Sep 18 16:29:50 2023 +0000 Make FnDef 1-ZST in LLVM debuginfo. commit bf9a1c8a193fc373897196321215794c8bebbeec Merge: 4f4a413fe69 7ecb09d05c0 Author: bors Date: Sun Oct 8 15:18:22 2023 +0000 Auto merge of #116515 - petrochenkov:nolegflavor, r=lqd linker: Remove unstable legacy CLI linker flavors commit 4f4a413fe6931d0ad9d3ac6bd20ff36398961e64 Merge: 1e3c8f196b2 eaafb256f8e Author: bors Date: Sun Oct 8 12:38:14 2023 +0000 Auto merge of #116454 - tmiasko:small-dominators, r=cjgillot Generalize small dominators optimization * Use small dominators optimization from 640ede7b0a1840415cb6ec881c2210302bfeba18 more generally. * Merge `DefLocation` and `LocationExtended` since they serve the same purpose. commit 005ec2e51ce99c6dd5e88c273b3f9b273fdf3f41 Author: Camille GILLOT Date: Sun Oct 8 12:08:09 2023 +0000 Do not run optimizations on trivial MIR. commit cc5db2c1c84169872f6278a3eb5f03c5abdef641 Merge: 81093441c16 2672876b63c Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun Oct 8 13:21:53 2023 +0200 Merge pull request #1397 from bjorn3/inline_asm_tweaks Test inline asm support on CI commit 1e3c8f196b2753b3e463bc6be2dc446f36653279 Merge: ab039f79b8a b704697fba5 Author: bors Date: Sun Oct 8 10:50:33 2023 +0000 Auto merge of #116183 - cjgillot:debug-dse-always, r=oli-obk Always preserve DebugInfo in DeadStoreElimination. This is a version of #106852 that does not check the current crate's debuginfo flag, and always attempts to preserve debuginfo. I haven't figured out how to handle mixing debuginfo levels for std, the one for the test, and the one for the CI target just right to merge #106852, so this can at least fix the debuginfo issue. Fixes https://github.com/rust-lang/rust/issues/103655 commit 89d610cd06f90cd6bd0bccdb395a3127290e1b45 Author: onur-ozkan Date: Sun Oct 8 13:41:56 2023 +0300 Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation Note that RUSTFLAGS_BOOTSTRAP should always be added to the end of RUSTFLAGS to be actually effective (e.g., if we have `-Dwarnings` in RUSTFLAGS, passing `-Awarnings` from RUSTFLAGS_BOOTSTRAP should override it). Signed-off-by: onur-ozkan commit a8830631b9446c8b48cd4eba1ef448eb5a258cdc Author: Ali MJ Al-Nasrawy Date: Sun Oct 8 10:06:17 2023 +0000 remove trailing dots commit 996ffcb718941fc36ec5fdee38ed99ce20ec06d5 Author: Ali MJ Al-Nasrawy Date: Sun Sep 17 14:32:02 2023 +0000 always show and explain sub region commit 5be0b2283aa26f0fee1e3d1161524a23d65484b7 Author: Ali MJ Al-Nasrawy Date: Fri Sep 8 01:35:51 2023 +0000 improve the suggestion of generic_bound_failure commit 2672876b63c4e4a46071c4661cc06098ab746eac Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Oct 7 11:14:24 2023 +0000 Run inline asm rustc tests on CI commit 91e5bd87e6ef2a3320bf610cb7cc2e2d64d7606f Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Oct 7 11:14:10 2023 +0000 Skip cpuid shim when inline asm support is enabled cg_clif should support enough simd intrinsics now to not need almost all cpu features to be force disabled. In addition they can't be disabled anyway when using a sysroot compiled by LLVM. commit 07147f34d0691a0709b0e1f5ef62c8029d2da58d Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Oct 7 11:12:46 2023 +0000 Fix inline asm on macOS commit 81093441c16dba56221bae016b394d0fb5dc57a2 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun Oct 8 09:30:32 2023 +0000 Rustup to rustc 1.75.0-nightly (97c81e1b5 2023-10-07) commit 1906ec56fce048588b319bfbc97126ba9d8c5de2 Merge: e759603da1d c9f6ac45d9a Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun Oct 8 09:22:39 2023 +0000 Sync from rust 97c81e1b537088f1881c8894ee8579812ed9b6d1 commit ab039f79b8a0cfea01fb8aa10860560b9689e4c6 Merge: 6d271692b0c b563595c6e6 Author: bors Date: Sun Oct 8 09:04:57 2023 +0000 Auto merge of #116514 - petrochenkov:nogccld, r=lqd linker: Remove `-Zgcc-ld` option It is subsumed by `-Clinker-flavor=*-lld-cc -Clink-self-contained=+linker` options now. r? `@lqd` commit 6d271692b0cc8ea1e91bbc8c090c88e7dbd5efe3 Merge: e08de860365 d9a7afec8b0 Author: bors Date: Sun Oct 8 07:13:19 2023 +0000 Auto merge of #116509 - Enselic:rustc-test-op, r=Mark-Simulacrum tests/run-make: Move RUSTC_TEST_OP to tools.mk and use in more places commit b563595c6e6002ab582e2eb4ebd2a19baa8a1e34 Author: Vadim Petrochenkov Date: Sat Oct 7 13:57:29 2023 +0300 linker: Remove `-Zgcc-ld` option It is subsumed by `-Clinker-flavor=*-lld-cc -Clink-self-contained=+linker` options now commit fea943debfab3859853ef623e06248ffbfd603ab Merge: c9f6ac45d9a 2753052adf3 Author: bors Date: Sun Oct 8 05:24:16 2023 +0000 Auto merge of #116487 - tamird:avoid-unwrap-absolute, r=bjorn3 compiler: env/path handling fixes Please see individual commits. r? `@bjorn3` cf. #116426 commit e08de860365aa73653dc5fc45b09f194785f3e57 Merge: 1516ca1bc01 3cac3de200a Author: bors Date: Sun Oct 8 05:24:16 2023 +0000 Auto merge of #116487 - tamird:avoid-unwrap-absolute, r=bjorn3 compiler: env/path handling fixes Please see individual commits. r? `@bjorn3` cf. #116426 commit 1516ca1bc01181af73c7b7760fb90137007da75f Merge: fdf32ee9fcd 5048f813130 Author: bors Date: Sun Oct 8 03:36:37 2023 +0000 Auto merge of #116486 - van-ema:master, r=nikic Fix to register analysis passes with -Zllvm-plugins at link-time This PR fixes an unexpected behavior of the `-Zllvm-plugins` flag. It allows to run an out-of-tree pass as part of LTO. However, analysis passes are registered before the plugin is loaded. As a result an analysis pass, which is passed as a plugin, is not registered. This causes the LLVM PassManager to fail when the analysis pass is queried from a transformation pass [(here)](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/PassManager.h#L776). This fix mimics the bahavior in [LLVM LTOBackend.cpp](https://github.com/llvm/llvm-project/blob/main/llvm/lib/LTO/LTOBackend.cpp#L273) by loading the plugin before the analysis passes are registered. Tested with rustc 1.60 and 1.65 and LLVM-13.0.1. commit fdf32ee9fcd259913c7dece8f7b915b2d5560a49 Merge: e9addfdecf1 098dd979393 Author: bors Date: Sun Oct 8 01:48:31 2023 +0000 Auto merge of #116450 - Kobzol:automation-try-bors-ci, r=Mark-Simulacrum Enable new bors try branch to run on CI Needed to fix [this error](https://github.com/rust-lang/rust/actions/runs/6420044833/job/17431256956). Inspired by https://github.com/rust-lang/rust/pull/99988 Also, removes `try-merge` from the workflow. It shouldn't have been added in https://github.com/rust-lang/rust/pull/116353. r? `@Mark-Simulacrum` commit e9addfdecf14633324fc5c935f4f2983699bef7e Merge: 97c81e1b537 209789ef4c2 Author: bors Date: Sun Oct 8 00:04:17 2023 +0000 Auto merge of #114623 - Kobzol:opt-dist-gha-summaries, r=Mark-Simulacrum Print some information from try builds to GitHub summary This PR adds some logs from `opt-dist` (the duration of the individual steps of the build pipeline, and the size of the resulting artifacts) to GitHub [job summaries](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/), in order to quickly show useful information right in the GHA CI job page, without needing to read the full log. [This](https://github.com/rust-lang-ci/rust/actions/runs/5810621086) is how the summary currently looks like. r? `@ghost` commit 97c81e1b537088f1881c8894ee8579812ed9b6d1 Merge: cf21a0823b8 e53c7787772 Author: bors Date: Sat Oct 7 20:59:32 2023 +0000 Auto merge of #116416 - Kobzol:ci-host-llvm-17-0-2, r=Mark-Simulacrum Bump host compiler on x64 dist Linux to LLVM 17.0.2 17.0.0-rc3 had a bunch of miscompilations, and it's probably better in general not to use a RC version of LLVM long term on CI. commit cf21a0823b8a863fb3f1ed33d7d31bfd4881c2d3 Merge: 598e29bf700 81d1f7ea9d8 Author: bors Date: Sat Oct 7 19:11:17 2023 +0000 Auto merge of #116437 - nnethercote:rustc_features, r=Nilstrieb Clean up `rustc_features` Plenty more to be done, but this is a decent start. r? `@Nilstrieb` commit 7ecb09d05c05daa437fba557b0f6733d6759c96c Author: Vadim Petrochenkov Date: Sat Oct 7 14:27:58 2023 +0300 linker: Remove unstable legacy CLI linker flavors commit 598e29bf70074de5ce2701a867450591083c4ff1 Merge: 935a091a783 258a65d4a20 Author: bors Date: Sat Oct 7 17:10:02 2023 +0000 Auto merge of #100806 - timvermeulen:split_inclusive_double_ended_bound, r=dtolnay Fix generic bound of `str::SplitInclusive`'s `DoubleEndedIterator` impl `str::SplitInclusive`'s `DoubleEndedIterator` implementation currently uses a `ReverseSearcher` bound for the corresponding searcher. A `DoubleEndedSearcher` bound should have been used instead. `DoubleEndedIterator` requires that repeated `next_back` calls produce the same items as repeated `next` calls, in opposite order. `ReverseSearcher` lets you search starting from the back of a string, but it makes no guarantees about how its matches correspond to the matches found by a forward search. `DoubleEndedSearcher` is a subtrait of `ReverseSearcher` and does require that the same matches are found in both directions. This bug fix is a breaking change. Calling `next_back` on `"a+++b".split_inclusive("++")` is currently accepted with repeated calls producing `"b"` and `"a+++"`, while forward iteration yields `"a++"` and `"+b"`. Also see https://github.com/rust-lang/rust/issues/100756#issuecomment-1221307166 for more details. I believe that this is the only iterator that uses this bound incorrectly — other related iterators such as `str::Split` do have a `DoubleEndedSearcher` bound for their `DoubleEndedIterator` implementation. And `slice::SplitInclusive` doesn't face this problem at all because it doesn't use patterns, only a predicate. cc `@SkiFire13` commit 935a091a7834253a845a92629b8f1109b5befa5d Merge: 91db3bdc8ce 8dc92a360c3 Author: bors Date: Sat Oct 7 15:21:05 2023 +0000 Auto merge of #116330 - RalfJung:dont-key-on-allocid, r=oli-obk remove Key impls for types that involve an AllocId I don't understand how but somehow that leads to issues like https://github.com/rust-lang/rust/issues/83085? Anyway removing unused impls doesn't seem like a bad idea. The concerning part is that of course nothing will stop us from having such impls again in the future, alongside re-introducing bugs like #83085. r? `@oli-obk` commit 91db3bdc8cefa5a9bd58b8fbc3ce5ef1859b4b93 Merge: 48e24629e94 56e4715fc6e Author: bors Date: Sat Oct 7 13:33:19 2023 +0000 Auto merge of #116310 - Enselic:check_fn_args_move_size, r=oli-obk rustc_monomorphize: Introduce check_fn_args_move_size() This is in preparation of improving diagnostics of "large moves into functions", a.k.a. passing args. Note: This PR consists of two self-contained commits that can be reviewed independently. For https://github.com/rust-lang/rust/issues/83518 Also see https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/arg.20Spans.20for.20TerminatorKind.3A.3ACall.3F r? `@oli-obk` who is E-mentor commit b0badc17cdc8d2f75061d2e4674a8adcfa8983d5 Author: Guillaume Gomez Date: Sat Oct 7 14:37:47 2023 +0200 Add cross-crate C-like variant test commit de70a77be235f839dede3c06fdb70c5528f540e6 Author: Guillaume Gomez Date: Sat Oct 7 14:37:30 2023 +0200 Correctly handle cross-crate C-like variants commit 1994d0b4a42b9b2d6e0c821f57d37a184f4df44a Author: Guillaume Gomez Date: Sat Oct 7 00:25:34 2023 +0200 Update enum-variant-value test commit 9e15f363be1f62cf81d4efb55d95a542663fe6da Author: Guillaume Gomez Date: Sat Oct 7 00:14:57 2023 +0200 Only display enum variants integer values if one of them has a value set commit e759603da1d281890cac241f244d2288c127b355 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Oct 7 09:47:03 2023 +0000 Consistently use eprintln inside the build system commit 48e24629e946339943b194163a81374cf533ce5a Merge: d087c6fae21 ad7045e160b Author: bors Date: Sat Oct 7 10:57:18 2023 +0000 Auto merge of #115583 - RalfJung:packed-unsized, r=lcnr fix detecting references to packed unsized fields Fixes https://github.com/rust-lang/rust/issues/115396 This is a breaking change, but permitted as a soundness fix. commit d087c6fae215484bf47ba6dda1bc836ef4c07ac5 Merge: 0f3d72aa7a7 cbe892fd659 Author: bors Date: Sat Oct 7 08:58:23 2023 +0000 Auto merge of #116457 - RalfJung:try_eval_scalar_int, r=cjgillot fix fast-path for try_eval_scalar_int Cc https://github.com/rust-lang/rust/pull/116281 `@Nadrieril` commit 56e4715fc6ef3cd8c008150ed0f1886a7696062f Author: Martin Nordholts Date: Sun Oct 1 09:03:41 2023 +0200 rustc_monomorphize: Introduce check_fn_args_move_size() So that we later can improve the accuracy of diagnostics. commit 41d24ccb49102bf6e2bfb5828f6d67abd8961e00 Author: Martin Nordholts Date: Sun Oct 1 08:51:47 2023 +0200 rustc_monomorphize: Move limit check into check_move_size() And rename to check_operand_move_size(). Later we will introduce check_fn_args_move_size(). commit 0f3d72aa7a71b58f487b7e4ed663cf5b23b746fd Merge: fc01a7432be a04b7a37445 Author: bors Date: Sat Oct 7 07:10:56 2023 +0000 Auto merge of #116508 - RalfJung:miri, r=RalfJung Miri subtree update r? `@ghost` commit d9a7afec8b079b16b6b6f2e23e1f375bc37b4abf Author: Martin Nordholts Date: Sat Oct 7 08:23:10 2023 +0200 tests/run-make: Use RUSTC_TEST_OP in more places commit 88966c477386db4ccabd18df3de52647d3540f96 Author: Martin Nordholts Date: Sat Oct 7 08:14:38 2023 +0200 tests/run-make: Move RUSTC_TEST_OP to tools.mk To reduce duplication. A follow-up commit will begin using it in even more places. commit f96541e9a9be7a5b28191be9229d72c8bf47baa7 Author: Martin Nordholts Date: Sat Oct 7 08:17:20 2023 +0200 tests/run-make: Remove wrong blessing advice run-make tests are not special but can be blessed like other tests, like this: ./x.py test --bless tests/run-make/unknown-mod-stdin commit a04b7a374458b640960798dffe83e614f7907562 Author: Ralf Jung Date: Sat Oct 7 07:56:15 2023 +0200 allow option-ext as a tool dependency (MPL licensed) commit 5aecfe467b94c1d1a5124b119a8864d6dce8596f Author: Ralf Jung Date: Sat Oct 7 07:55:48 2023 +0200 update lockfile commit fc01a7432be662270467a4c3fa4a38811b621d9d Merge: 4ea5190026d 6b98dcc743b Author: bors Date: Sat Oct 7 05:26:12 2023 +0000 Auto merge of #109214 - tosti007:std_collection_hash_new_rework, r=workingjubilee Use `HashMap::with_capacity_and_hasher` instead of using base Cleans up the internal logic for `HashMap::with_capacity` slightly. commit 1c42857135ca902122fdbe6e050ba1481431541b Merge: 3b08930677e 722736ac4ab Author: bors Date: Sat Oct 7 05:18:45 2023 +0000 Auto merge of #3113 - rust-lang:rustup-2023-10-07, r=saethlin Automatic sync from rustc commit 722736ac4ab71b34645149b6994c0d56c6143832 Merge: d322243e388 4ea5190026d Author: The Miri Conjob Bot Date: Sat Oct 7 05:10:55 2023 +0000 Merge from rustc commit d322243e38808ab0078a8ecad32d31c8f5d8060e Author: The Miri Conjob Bot Date: Sat Oct 7 05:01:29 2023 +0000 Preparing for merge from rustc commit 4ea5190026dbc1302b644d938e68bc6843cb8b24 Merge: 93b6a365680 93677276bc4 Author: bors Date: Sat Oct 7 02:20:50 2023 +0000 Auto merge of #116318 - pitaj:android-backtrace-build, r=workingjubilee Invoke `backtrace-rs` buildscript in `std` buildscript Based on #99883 by `@Arc-blroth` Depends on rust-lang/backtrace-rs#556 and rust-lang/cc-rs#705 commit 93b6a36568027e44a7345ae8d577c0d13545c79f Merge: 8fdb0a9b578 4b102b0d8d8 Author: bors Date: Sat Oct 7 00:27:14 2023 +0000 Auto merge of #116501 - workingjubilee:rollup-fpzov6m, r=workingjubilee Rollup of 4 pull requests Successful merges: - #116277 (dont call mir.post_mono_checks in codegen) - #116400 (Detect missing `=>` after match guard during parsing) - #116458 (Properly export function defined in test which uses global_asm!()) - #116500 (Add tvOS to target_os for register_dtor) r? `@ghost` `@rustbot` modify labels: rollup commit 4b102b0d8d8212bd2aca7ddd9ff8f699844e37c3 Merge: 5268120d4a1 3abef68e63e Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri Oct 6 16:37:48 2023 -0700 Rollup merge of #116500 - simlay:tvos-support-for-register_dtor, r=workingjubilee Add tvOS to target_os for register_dtor Closes #116491. commit 5268120d4a10a879b0fe8aae0ffa9443b3e45266 Merge: 0d68e416a56 ecf271cfb62 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri Oct 6 16:37:47 2023 -0700 Rollup merge of #116458 - bjorn3:fix_global_asm_test, r=workingjubilee Properly export function defined in test which uses global_asm!() Currently the test passes with the LLVM backend as the codegen unit partitioning logic happens to place both the global_asm!() and the function which calls the function defined by the global_asm!() in the same CGU. With the Cranelift backend it breaks however as it will place all assembly in separate codegen units to be passed to an external linker. commit 0d68e416a568ae0e206bcf65a2c5234565ba3bf5 Merge: 6d1c3a40cb4 8fd345dd4b8 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri Oct 6 16:37:47 2023 -0700 Rollup merge of #116400 - estebank:issue-78585, r=WaffleLapkin Detect missing `=>` after match guard during parsing ``` error: expected one of `,`, `:`, or `}`, found `.` --> $DIR/missing-fat-arrow.rs:25:14 | LL | Some(a) if a.value == b { | - while parsing this struct LL | a.value = 1; | -^ expected one of `,`, `:`, or `}` | | | while parsing this struct field | help: try naming a field | LL | a: a.value = 1; | ++ help: you might have meant to start a match arm after the match guard | LL | Some(a) if a.value == b => { | ++ ``` Fix #78585. commit c9f6ac45d9a57e60ed4b2d63c96af49be2219ba1 Merge: ed900871cfc ffa2d3ab632 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri Oct 6 16:37:46 2023 -0700 Rollup merge of #116277 - RalfJung:post-mono, r=oli-obk dont call mir.post_mono_checks in codegen It seems like all tests are still passing when I remove this... let's see what CI says. commit 6d1c3a40cb4ce7b455e44834f79c5ecf39cd5021 Merge: 960754090ac fa248cd9e69 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri Oct 6 16:37:46 2023 -0700 Rollup merge of #116277 - RalfJung:post-mono, r=oli-obk dont call mir.post_mono_checks in codegen It seems like all tests are still passing when I remove this... let's see what CI says. commit 8fdb0a9b578ddbe7246d8088a93c09b7679c4616 Merge: 960754090ac 3706e6f61a9 Author: bors Date: Fri Oct 6 22:39:41 2023 +0000 Auto merge of #114709 - ShE3py:wasi-io-error-more, r=workingjubilee Use `io_error_more` on WASI #86442 added many variants to [`io::ErrorKind`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html), but `sys::wasi::decode_error_kind()` wasn't modified to use them. The preview1 `errno` list: https://github.com/WebAssembly/WASI/blob/4712d490fd7662f689af6faa5d718e042f014931/legacy/preview1/docs.md#-errno-variant Original implementation: #63814 `@rustbot` label +A-error-handling +C-enhancement +O-wasi commit 3abef68e63e12a1c6af2e09c2f020f778d2892ee Author: Sebastian Imlay Date: Fri Oct 6 18:11:49 2023 -0400 Add tvOS to target_os for register_dtor commit 91114d6616f58996b6009bcb23196e8dc253e8bf Author: Guillaume Gomez Date: Fri Oct 6 23:55:30 2023 +0200 Show values of C-like variants even if not defined by the user commit 960754090acc9cdd2a5a57586f244c0fc712d26c Merge: 94bc9c737ea 7f0cf8c0e41 Author: bors Date: Fri Oct 6 20:51:40 2023 +0000 Auto merge of #116492 - matthiaskrgr:rollup-xzfhmq1, r=matthiaskrgr Rollup of 7 pull requests Successful merges: - #114564 (Attempt to describe the intent behind the `From` trait further) - #116297 (add some docs to hooks/mod.rs) - #116423 (Fix typo in attrs.rs) - #116466 (`rustc_transmute` cleanups) - #116474 (Assorted small cleanups) - #116481 (Reuse existing `Some`s in `Option::(x)or`) - #116484 (Minor doc clarification in Once::call_once) r? `@ghost` `@rustbot` modify labels: rollup commit 7f0cf8c0e41dd5df27edfa57d42399dbab634320 Merge: f8dae0c20a0 c95015c2955 Author: Matthias Krüger Date: Fri Oct 6 21:17:51 2023 +0200 Rollup merge of #116484 - peterjoel:once-doc-clarify, r=cuviper Minor doc clarification in Once::call_once commit f8dae0c20a03a584c12146c89253e2c2ef93d4b2 Merge: 9796dfdd563 5432d13bb04 Author: Matthias Krüger Date: Fri Oct 6 21:17:50 2023 +0200 Rollup merge of #116481 - scottmcm:tweak-combinators, r=cuviper Reuse existing `Some`s in `Option::(x)or` LLVM still has trouble re-using discriminants sometimes when rebuilding a two-variant enum, so when we have the correct variant already built, just use it. That's shorter in the Rust code, as well as simpler in MIR and the optimized LLVM, so might as well: Thanks to `@veber-alex` for pointing out this opportunity in https://github.com/rust-lang/rust/issues/101210#issuecomment-1732470941 commit 9796dfdd563d9b7d09088b94b8e3314c61a3786c Merge: 25fbd133ea4 e7dabc9f877 Author: Matthias Krüger Date: Fri Oct 6 21:17:50 2023 +0200 Rollup merge of #116474 - nnethercote:rustc_assorted, r=spastorino Assorted small cleanups r? `@spastorino` commit 25fbd133ea4a0cf3e76820fa09d4a7cdaeb62775 Merge: 81192f2fc46 29ed8e492ab Author: Matthias Krüger Date: Fri Oct 6 21:17:49 2023 +0200 Rollup merge of #116466 - nnethercote:rustc_transmute, r=oli-obk `rustc_transmute` cleanups Just some things I found while poking around this code. r? `@oli-obk` commit 81192f2fc46ee8483efc908314d8c5f5e314799d Merge: fdb136a83f3 23efab4811c Author: Matthias Krüger Date: Fri Oct 6 21:17:49 2023 +0200 Rollup merge of #116423 - eltociear:patch-22, r=flip1995 Fix typo in attrs.rs documenation -> documentation commit fdb136a83f32555c76911e9c77f62ad21cbfadd3 Merge: 4dfa5e5dec5 13e58755d7c Author: Matthias Krüger Date: Fri Oct 6 21:17:48 2023 +0200 Rollup merge of #116297 - RalfJung:hooks, r=oli-obk add some docs to hooks/mod.rs r? `@oli-obk` commit 4dfa5e5dec58f7c510b6e3722fa74b244d4ba887 Merge: 31be8cc4114 1651f1f4b8f Author: Matthias Krüger Date: Fri Oct 6 21:17:48 2023 +0200 Rollup merge of #114564 - scottmcm:when-to-from, r=dtolnay Attempt to describe the intent behind the `From` trait further Inspired by the thread. `@rustbot` label +T-libs-api commit 94bc9c737ea97d56f9b4076553ac37c05c1e3931 Merge: 31be8cc4114 4483ac2206d Author: bors Date: Fri Oct 6 18:44:32 2023 +0000 Auto merge of #114811 - estebank:impl-ambiguity, r=wesleywiser Show more information when multiple `impl`s apply - When there are `impl`s without type params, show only those (to avoid showing overly generic `impl`s). ``` error[E0283]: type annotations needed --> $DIR/multiple-impl-apply.rs:34:9 | LL | let y = x.into(); | ^ ---- type must be known at this point | note: multiple `impl`s satisfying `_: From` found --> $DIR/multiple-impl-apply.rs:14:1 | LL | impl From for Bar { | ^^^^^^^^^^^^^^^^^^^^^^ ... LL | impl From for Foo { | ^^^^^^^^^^^^^^^^^^^^^^ = note: required for `Baz` to implement `Into<_>` help: consider giving `y` an explicit type | LL | let y: /* Type */ = x.into(); | ++++++++++++ ``` - Lower the importance of `T: Sized`, `T: WellFormed` and coercion errors, to prioritize more relevant errors. The pre-existing deduplication logic deals with hiding redundant errors better that way, and we show errors with more metadata that is useful to the user. - Show `::assoc_fn` suggestion in more cases. ``` error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/cross-return-site-inference.rs:38:16 | LL | return Err(From::from("foo")); | ^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | LL | return Err(::from("foo")); | +++++++++++++++++++ + ``` Fix #88284. commit 3706e6f61a95225ce6cf3dca4c3d0b86545d9090 Author: ShE3py <52315535+she3py@users.noreply.github.com> Date: Fri Oct 6 19:05:45 2023 +0200 Use `io_error_more` on WASI commit 31be8cc41148983e742fea8f559aacca0f6647db Merge: 64fa0c34d7c 6233d44815c Author: bors Date: Fri Oct 6 16:46:13 2023 +0000 Auto merge of #116489 - flip1995:clippyup, r=Manishearth Clippy subtree sync r? `@Manishearth` commit fa248cd9e6927dd6981078963aa47feb941a0d10 Author: Ralf Jung Date: Fri Oct 6 18:25:23 2023 +0200 add some comments explaining how the required_consts stuff fits together commit 3b08930677e5f9b5999caa2e5960df8def1b1e73 Merge: 375ff3e5ce5 100ea2b4999 Author: bors Date: Fri Oct 6 16:25:15 2023 +0000 Auto merge of #3112 - RalfJung:rustup, r=RalfJung Rustup preparing for rustc-push commit 100ea2b499955b2e0814719317c4092f95f988b1 Merge: ea56007362c 3706e6f61a9 Author: Ralf Jung Date: Fri Oct 6 18:15:20 2023 +0200 Merge from rustc commit ea56007362cf04da6d776a89fa45f536c537c448 Author: Ralf Jung Date: Fri Oct 6 18:15:12 2023 +0200 Preparing for merge from rustc commit 4483ac2206dd6ed1f80a9d1769a5635b1980d288 Author: Esteban Küber Date: Thu Oct 5 03:57:10 2023 +0000 Fix windows test that has different stderr output commit 6233d44815ce681062fca851a254f2a37db7916e Author: Philipp Krones Date: Fri Oct 6 17:47:56 2023 +0200 Update Cargo.lock commit b704697fba5a1621000fbfbd53231cfa0b388878 Author: Camille GILLOT Date: Tue Sep 26 21:13:31 2023 +0000 Bless incremental tests. commit 27d6a57e5821c8b7f5c8b049e36b856ed9440bfe Author: Camille GILLOT Date: Thu Jan 12 20:04:42 2023 +0000 Preserve DebugInfo in DeadStoreElimination. commit 375ff3e5ce54156db1443dca021e72a6ff8ec75c Merge: 3c511bb4178 e1e880e9c6a Author: bors Date: Fri Oct 6 15:44:37 2023 +0000 Auto merge of #3110 - eduardosm:rounding-without-host-floats, r=RalfJung Do not use host floats in `simd_{ceil,floor,round,trunc}` commit 3c8c3ad6dfa95afcf4e70ccd692f976fc238e24c Merge: 1bc0463b183 b105fb4c39b Author: Philipp Krones Date: Fri Oct 6 17:35:45 2023 +0200 Merge commit 'b105fb4c39bc1a010807a6c076193cef8d93c109' into clippyup commit b105fb4c39bc1a010807a6c076193cef8d93c109 Merge: 7217c0f3ac1 b8677e54d4e Author: bors Date: Fri Oct 6 15:34:34 2023 +0000 Auto merge of #11629 - flip1995:rustup, r=flip1995 Rustup r? `@ghost` changelog: none commit b8677e54d4eb2181f539864d3594a0dd62f2f0d9 Author: Philipp Krones Date: Fri Oct 6 17:32:44 2023 +0200 Bump Clippy version -> 0.1.75 commit 50754da9fa2f956eed5af672ed3c7820d774ce91 Author: Philipp Krones Date: Fri Oct 6 17:32:32 2023 +0200 Bump nightly version -> 2023-10-06 commit 82c3064c47599978b4cbc11330a6c593219125ec Merge: c5c6d703de7 7217c0f3ac1 Author: Philipp Krones Date: Fri Oct 6 17:27:17 2023 +0200 Merge remote-tracking branch 'upstream/master' into rustup commit 7217c0f3ac15a20dd1cc1d5bc02f084f40db8029 Merge: 279127ce2e5 48d2770e527 Author: bors Date: Fri Oct 6 15:06:00 2023 +0000 Auto merge of #11628 - koka831:fix/11625, r=blyxyas Improve `redundant_locals` help message Fixes #11625 AFAIK, `span_lint_and_help` points the beginning of spans when we pass multiple spans to the second argument, so This PR I also modified its help span and its message. lint result of the given example in the issue will be: ```console error: redundant redefinition of a binding `apple` --> src/main.rs:5:5 | 5 | let apple = apple; | ^^^^^^^^^^^^^^^^^^ | help: `apple` is initially defined here --> src/main.rs:4:9 | 4 | let apple = 42; | ^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_locals ``` I hope that this change might help reduce user confusion, but I'd appreciate alternative suggestions:) changelog: [`redundant_locals`]: Now points at the rebinding of the variable commit 3c511bb41780f50cf7eef5a5e1e8a8804ae13ab9 Merge: 4587c7c1c04 bf1356efc3d Author: bors Date: Fri Oct 6 14:58:31 2023 +0000 Auto merge of #3067 - Vanille-N:spurious-incremental, r=RalfJung Continuation of #3054: enable spurious reads in TB The last additions to the test suite of TB left some unresolved `#[should_panic]` that these new modifications solve. ## Problem Recall that the issues were arising from the interleavings that follow. ### A. `Reserved -> Frozen` has visible effects after function exit The transition `Reserved -> Frozen` irreversibly blocks write accesses to the tag, so in the interleaving below `y` initially `Reserved` becomes `Frozen` only in the target where a spurious read through `x` is inserted. This makes the later write through `y` UB only in the target and not in the source. ``` 1: retag x (&, protect) 2: retag y (&mut, protect) 1: spurious read x 1: ret x 2: ret y 2: write y ``` ### B. Protectors only announce their presence on retag There is a read-on-reborrow for protected locations, but if the retag of `x` occurs before that of `y` and there is no explicit access through `x`, then `y` is unaware of the existence of `x`. This is problematic because a spurious read inserted through `x` between the retag of `y` and the return of the function protecting `x` is a noalias violation in the target without UB in the source. ``` 1: retag x (&, protect) 2: retag y (&mut, protect) 1: spurious read x 1: ret x 2: write y 2: ret y ``` ## Step 1: Finer behavior for `Reserved` Since one problem is that `Reserved -> Frozen` has consequences beyond function exit, we decide to remove this transition entirely. To replace it we introduce a new subtype of `Reserved` with the extra boolean `aliased` set. `Reserved { aliased: true }` forbids child accesses, but only temporarily: it has no effect on activation once the tag is no longer protected. This makes the semantics of Tree Borrows slightly weaker in favor of being more similar to noalias. This solves interleaving **A.**, but **B.** is still a problem and the exhaustive tests do not pass yet. ## Step 2: Read on function exit Protected tags issue a "reminder" that they are protected until this instant inclusive, in the form of an implicit read (symmetrically to the implicit read on retag). This ensures that if the periods on which two tags `x` and `y` are protected overlap then no matter the interleaving of retags and returns, there is either a protector currently active or a read that has been emitted, both of which temporarily block activation. This makes the exhaustive test designed previously pass, but it has an effect on the ability to return an activated pointer that I had not foreseen before implementing it. ## Step 2': Do not propagate to children A naive implementation of **Step 2** makes the following code UB: ```rs fn reborrow(x: &mut u8) -> &mut u8 { let y = &mut *x; *y = *y; y // callee returns `y: Active`... } let x = &mut 0u8; let y = reborrow(x); // ... and caller receives `y: Frozen` *y = 1; // UB ``` This is unacceptable, and a simple fix is to make this implicit read visible only to foreign tags. We still lack hindsight on the ramifications of this decision, and the fact that the problematic pattern was only discovered because it occured in one completely unrelated test (with a cryptic error message) is worrying. We should be vigilant as to how this interacts with the rest of the model. ## TODO As of commit #281c30, the data race model has not been fully updated. We have removed the reborrow of mutable references counting as a write access, but we still need the implicit read of function exit to count as a read. commit 64fa0c34d7cb1a2d522414ab2c87024e465bd613 Merge: 1bc0463b183 8a1be9942d6 Author: bors Date: Fri Oct 6 14:57:09 2023 +0000 Auto merge of #115304 - Enselic:trailing-gt, r=cjgillot Allow file names to end with '>' The [`rustc_span::FileName`](https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/enum.FileName.html) enum already differentiates between real files and "fake" files such as ``. We do not need to artificially forbid real file names from ending in `>`. Closes #73419 commit 279127ce2e5db187501e24631b49d635bae04865 Merge: 9554e477c29 dcc400191e4 Author: bors Date: Fri Oct 6 14:19:45 2023 +0000 Auto merge of #11611 - Alexendoo:items-after-test-module-check-crate, r=blyxyas Fix `items_after_test_module` for non root modules, add applicable suggestion Fixes #11050 Fixes #11153 changelog: [`items_after_test_module`]: Now suggests a machine-applicable suggestion. changelog: [`items:after_test_module`]: Also lints for non root modules commit 3cac3de200a99ed29583ce95705696e4b4782c76 Author: Tamir Duberstein Date: Fri Oct 6 08:35:45 2023 -0400 rustc_metadata: use try_canonicalize This is simpler and avoids unnecessary calls to `env::current_dir`. rustc_plugin is left unchanged to avoid conflicts with #116412. Updates #116426. commit 5aeb6a326f2fa941061b60c9286665847fe0401e Author: Tamir Duberstein Date: Fri Oct 6 08:32:00 2023 -0400 rustc_codegen_ssa: use try_canonicalize in rpath This is simpler and avoids unnecessary calls to `env::current_dir`. commit 48d2770e527dd21fd8ae71178d360abd005b6ddc Author: koka Date: Fri Oct 6 22:18:11 2023 +0900 Improve `redundant_locals` help message commit e1e880e9c6a8c756195720a51c0c0b5b1819d959 Author: Eduardo Sánchez Muñoz Date: Fri Oct 6 15:12:36 2023 +0200 Do not use host floats in `simd_{ceil,floor,round,trunc}` commit 1bc0463b183392ad4e0ae9c5f7a76630d487230d Merge: 6683f13fa1b 5674092e76f Author: bors Date: Fri Oct 6 13:07:15 2023 +0000 Auto merge of #116483 - GuillaumeGomez:rollup-z65pno1, r=GuillaumeGomez Rollup of 6 pull requests Successful merges: - #115454 (Clarify example in docs of str::char_slice) - #115522 (Clarify ManuallyDrop bit validity) - #115588 (Fix a comment in std::iter::successors) - #116198 (Add more diagnostic items for clippy) - #116329 (update some comments around swap()) - #116475 (rustdoc-search: fix bug with multi-item impl trait) r? `@ghost` `@rustbot` modify labels: rollup commit a081007265044a7baa0f23c286b6380be35c8bb0 Author: Tamir Duberstein Date: Fri Oct 6 08:22:35 2023 -0400 rustc_driver: avoid fallible conversions Use `std::path::PathBuf` rather than `String`; use `std::env::var_os` rather than `std::env::var`. These changes avoid a number of error paths which can arise in the presence of non-UTF-8 paths. commit 2753052adf3b21f7af1218b6a325484a5481658e Author: Tamir Duberstein Date: Fri Oct 6 08:51:30 2023 -0400 compiler: always use var_os("RUST_BACKTRACE") There are 3 instances of var(...) and 3 instances of var_os(...); the latter avoids an appearance of unhandled error, so use it everywhere. commit 7654d4b39833bc6fc0b0bcd184a616ff6ac7d9bd Author: Tamir Duberstein Date: Fri Oct 6 08:51:30 2023 -0400 compiler: always use var_os("RUST_BACKTRACE") There are 3 instances of var(...) and 3 instances of var_os(...); the latter avoids an appearance of unhandled error, so use it everywhere. commit dcc400191e444c8a57869f5004fdcbab807f7f09 Author: Alex Macleod Date: Wed Oct 4 20:24:16 2023 +0000 Fix `items_after_test_module` for non root modules, add applicable suggestion commit bf1356efc3d3d2c6b5c3fb3157d234f7a0901bc8 Author: Neven Villani Date: Wed Sep 20 14:27:20 2023 +0200 Fix problems of Reserved -> Frozen Reserved loses permissions too quickly. Adding more fine-grained behavior of Reserved lets it lose write permissions only temporarily. Protected tags receive a read access on initialized locations. commit 5048f813130f5c50fb95b784ad14ff40477c500b Author: Emanuele Vannacci Date: Fri Oct 6 12:04:28 2023 +0000 fix to register analysis pass from llvm plugin commit c95015c2955e8507f93a1106fa3f7eaafc25308b Author: Peter Hall Date: Fri Oct 6 12:20:39 2023 +0100 Minor doc clarification in Once::call_once commit 5674092e76f3736239910c892bf459ac686f47d1 Merge: 9e28a9349ce 1eb2a766417 Author: Guillaume Gomez Date: Fri Oct 6 13:18:35 2023 +0200 Rollup merge of #116475 - notriddle:notriddle/impl-trait-null, r=GuillaumeGomez rustdoc-search: fix bug with multi-item impl trait Preview searches: - https://notriddle.com/rustdoc-html-demo-5/compiler-doc-impl-trait-bugfix/index.html?search=-%3E%20globalctxt - https://notriddle.com/rustdoc-html-demo-5/compiler-doc-impl-trait-bugfix/index.html?search=globalctxt commit 9e28a9349ce31ce0a246c4f76ae44c6efbf53545 Merge: 3785fed021d bfc0f23acb4 Author: Guillaume Gomez Date: Fri Oct 6 13:18:35 2023 +0200 Rollup merge of #116329 - RalfJung:swap-comments, r=scottmcm update some comments around swap() Based on ``@eddyb's`` comment [here](https://github.com/rust-lang/unsafe-code-guidelines/issues/461#issuecomment-1742156410). And then I noticed the wrong capitalization for Miri and fixed it in some other places as well. commit 3785fed021dd834ebe40812c0e0f896cbcc5dce5 Merge: 382701e6b6c d464b72970f Author: Guillaume Gomez Date: Fri Oct 6 13:18:34 2023 +0200 Rollup merge of #116198 - Jarcho:diag_items, r=WaffleLapkin Add more diagnostic items for clippy commit 382701e6b6c4b65b5f4a00d6092cf8cef91f1181 Merge: 525c661842b 71429f5fd23 Author: Guillaume Gomez Date: Fri Oct 6 13:18:34 2023 +0200 Rollup merge of #115588 - tifv:fix-comment-successors, r=scottmcm Fix a comment in std::iter::successors The `unfold` function have since #58062 been renamed to `from_fn`. (I'm not sure if this whole comment is still useful—it's not like there are many iterators that *can't* be based on `from_fn`. Anyway, in its current form this comment is not correct, and it sent me into a half-hour research of what happened to `unfold` function, so I want to do *something* with it :upside_down_face: deleting these three lines is a perfectly fine alternative, in my opinion.) commit 525c661842b5fd6be5b191a4f6baa2c79d722e36 Merge: 4e818f6b723 a16622f62f1 Author: Guillaume Gomez Date: Fri Oct 6 13:18:33 2023 +0200 Rollup merge of #115522 - joshlf:patch-8, r=scottmcm Clarify ManuallyDrop bit validity Clarify that `ManuallyDrop` has the same bit validity as `T`. commit 4e818f6b72398ff1693b7372b24af0e24a1bc07e Merge: d4ba2b4c7c9 dfdab8fc629 Author: Guillaume Gomez Date: Fri Oct 6 13:18:33 2023 +0200 Rollup merge of #115454 - vwkd:patch-1, r=scottmcm Clarify example in docs of str::char_slice Just a one word improvement. “Last” can be misread as meaning the last (third) instead of the previous (first). commit 6683f13fa1ba91ab84dd5bc5bc21965a1b0530e1 Merge: d4ba2b4c7c9 9baab45e2f2 Author: bors Date: Fri Oct 6 11:12:13 2023 +0000 Auto merge of #111595 - fortanix:raoul/waitqueue_clarifications, r=workingjubilee `waitqueue` clarifications for SGX platform The documentation of `waitqueue` functions on the `x86_64-fortanix-unknown-sgx` platform is incorrect at some places and on others missing. This PR improves upon this. cc: `@jethrogb` commit ecf271cfb6224fae07a2b096bfbae22c6112b011 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri Oct 6 11:02:11 2023 +0000 Use pushsection/popsection commit 4587c7c1c044652a89104b8dccfd8e025aea177f Merge: 413540837b9 03a03e2ef66 Author: bors Date: Fri Oct 6 09:11:14 2023 +0000 Auto merge of #3109 - RalfJung:dlsym, r=RalfJung add a direct dlsym test commit 03a03e2ef66f80548681b8dbbf387b55e7b8a3cb Author: Ralf Jung Date: Fri Oct 6 11:06:16 2023 +0200 add a direct dlsym test commit 5432d13bb04cecf213c2753b25cfb1e366cb8026 Author: Scott McMurray Date: Fri Oct 6 01:41:48 2023 -0700 Reuse existing `Some`s in `Option::(x)or` LLVM still has trouble re-using discriminants sometimes when rebuilding a two-variant enum, so when we have the correct variant already built, just use it. That's simpler in LLVM *and* in MIR, so might as well: commit d4ba2b4c7c938cf90c03a265cb31356537f608ad Merge: ff057893b8a e300847864f Author: bors Date: Fri Oct 6 08:04:53 2023 +0000 Auto merge of #116018 - DianQK:simd-wide-sum-test, r=scottmcm Increasing the SIMD size improves the vectorization possibilities Change the `simd-wide-sum.rs` to pass tests based on the LLVM main branch. For smaller lengths, we cannot expect to always get vectorized. A related discussion at https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm/topic/LLVM.20HEAD.3A.20codegen.2Fsimd.2Fsimd-wide-sum.2Ers.20newly.20failing. r? scottmcm commit 413540837b904e7cdf5d2b5ff137867268868095 Merge: f9003c08ab2 16cde069fc7 Author: bors Date: Fri Oct 6 07:40:47 2023 +0000 Auto merge of #3108 - RalfJung:dlsym, r=RalfJung refactor dlsym: dispatch symbols via the normal shim mechanism This avoids having to adjust Miri when switching between invoking the function via a linked symbol vs via dlsym. commit 16cde069fc7e727dca3c6d8ec5077f0d2f6f928b Author: Ralf Jung Date: Fri Oct 6 09:38:50 2023 +0200 allow dyn_sym in the files where they are defined; remove unreachable android code commit 099311ba5a15162d73afe9ebe62bdc463ebd76c0 Author: Ralf Jung Date: Fri Oct 6 09:20:51 2023 +0200 make some things on foreign_items private commit bc8d4dfa95ae10c3f7229c01710a9e8f838baaec Author: Ralf Jung Date: Fri Oct 6 09:15:48 2023 +0200 refactor dlsym: dispatch symbols via the normal shim mechanism commit e300847864faf93538354b418da0a1612efd36f4 Author: scottmcm Date: Fri Oct 6 07:05:09 2023 +0000 Add a wishlist FIXME commit 1651f1f4b8f97a51f1699101cfe03ea129ec7a07 Author: Scott McMurray Date: Thu Oct 5 23:03:02 2023 -0700 Elaborate some caveats to lossless commit f9003c08ab2e5d331ebd9285cc3a205d0b4c956c Merge: 1a6ab015d00 dff7d5aa2f0 Author: bors Date: Fri Oct 6 05:52:07 2023 +0000 Auto merge of #3098 - BlackHoleFox:apple-entropy, r=RalfJung Support getentropy on macOS as a foreign item Prior this was always assumed to be accessed via `dlsym` shim, but in `std` I'm attempting to start [unconditionally linking](https://github.com/rust-lang/rust/pull/116319) to `getentropy` on macOS now that Rust's platform version support allows it. This just moves the main logic of the previous `dlsym` handler into an eval context extension so it can be used via both call paths. The `dlsym` handler is still needed as `getrandom` uses it. commit dff7d5aa2f041f833901318ab8d301aeeb8ef06c Author: BlackHoleFox Date: Sun Oct 1 12:19:41 2023 -0500 Move getentropy handling to a shared location for foreign item implementation commit ff057893b8a2f20de2ff258ed8690f5a42fed78a Merge: fd80c02c168 b29777a1862 Author: bors Date: Fri Oct 6 05:34:36 2023 +0000 Auto merge of #116472 - matthiaskrgr:rollup-1mz0qrp, r=matthiaskrgr Rollup of 2 pull requests Successful merges: - #116421 (Clarify `invalid_reference_casting` lint around interior mutable types) - #116469 (Fix typo in README.md) r? `@ghost` `@rustbot` modify labels: rollup commit 1eb2a766417c755f6787358bfc36385a26c4ed31 Author: Michael Howell Date: Thu Oct 5 22:32:37 2023 -0700 rustdoc-search: fix bug with multi-item impl trait commit 44f92c1f805434866b9744a6c8953ecdd8cc36f9 Author: scottmcm Date: Fri Oct 6 05:31:54 2023 +0000 Don't mention "recover the original" in `From` docs Co-authored-by: Josh Triplett commit b80e653ca1278a2c4fa411b938be1ccc7ed204fb Author: Scott McMurray Date: Sun Aug 6 14:54:55 2023 -0700 Attempt to describe the intent behind the `From` trait further commit b29777a18627464864611cb595677f21623e1be8 Merge: 7d7004d3e64 6ff3c3a421c Author: Matthias Krüger Date: Fri Oct 6 06:23:48 2023 +0200 Rollup merge of #116469 - prakashAditya639:master, r=workingjubilee Fix typo in README.md the word "programatically" should be corrected to "programmatically." commit 7d7004d3e64c27cdc71b06c177506edc11040410 Merge: 579be69de9f e46236cceb0 Author: Matthias Krüger Date: Fri Oct 6 06:23:48 2023 +0200 Rollup merge of #116421 - Urgau:inter-mut-invalid_ref_casting, r=oli-obk Clarify `invalid_reference_casting` lint around interior mutable types This is PR intends to clarify the `invalid_reference_casting` lint around interior mutable types by adding a note for them saying that they should go through `UnsafeCell::get`. So for this code: ```rust let cell = &std::cell::UnsafeCell::new(0); let _num = &mut *(cell as *const _ as *mut i32); ``` the following note will be added to the lint output: ```diff error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:68:16 | LL | let _num = &mut *(cell as *const _ as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, visit + = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get` ``` Suggestion are welcome around the note contents. Fixes https://github.com/rust-lang/rust/issues/116410 cc `@RalfJung` commit e7dabc9f877d76e0a3432100d83b14b97978533d Author: Nicholas Nethercote Date: Fri Oct 6 14:59:11 2023 +1100 Remove unnecessary `pub`. commit 093b435b786dfd816aba790f0097943258a1b366 Author: Nicholas Nethercote Date: Fri Oct 6 14:58:01 2023 +1100 Remove unneeded features. commit 4b51a3eb52c5ae292ba54c2044be695630fccc3e Author: Nicholas Nethercote Date: Fri Oct 6 14:57:25 2023 +1100 Remove unneeded dependency. Also sort them. commit e49a1470baee89823a49aa6ec7baa19aa033b88b Author: Nicholas Nethercote Date: Wed Oct 4 18:27:18 2023 +1100 Factor out `insert_or_error`. It appears identically as a closure in two functions. Also change its return type from `bool` to `Option<()>` so it can be used with `?`. commit 108e541cc2d73fc4548847a2cfddca5c3b3499e6 Author: Nicholas Nethercote Date: Wed Oct 4 15:37:44 2023 +1100 Remove unused `FileName::CfgSpec`. commit 442a66d385bc2cdaf53b042437b9997d7b163d6d Author: Nicholas Nethercote Date: Tue Oct 3 17:03:58 2023 +1100 Remove unneeded dependency. commit fd80c02c168c2dfbb82c29d2617f524d2723205b Merge: 579be69de9f c8f3aa451a0 Author: bors Date: Fri Oct 6 03:39:22 2023 +0000 Auto merge of #116463 - ChrisDenton:nlibc, r=workingjubilee Remove libc We don't use much libc on Windows and it seemed silly to keep if for the sake of [two well documented constants](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170). commit 6ff3c3a421c23490751685c6a8cc41bee53bdc55 Author: AdityaPrakash <138978307+prakashAditya639@users.noreply.github.com> Date: Fri Oct 6 09:05:38 2023 +0530 typo in README.md commit 579be69de9f98f56d92b93820eaf7e6b06b517a5 Merge: 2c9b0de8ea5 905f49a7287 Author: bors Date: Fri Oct 6 01:50:10 2023 +0000 Auto merge of #101150 - jethrogb:jb/cleanup-sgx-user-memory-copies, r=workingjubilee Clean up SGX user memory copies Follow-up on #98126 and #100383 r? `@cuviper` cc `@raoulstrackx` commit 29ed8e492ab99391e9eaa1247fbafe2759f9c383 Author: Nicholas Nethercote Date: Fri Oct 6 11:25:32 2023 +1100 Remove the `MaybeTransmutableQuery<&'l Dfa<...>, C>` impl. Because there is also a `MaybeTransmutableQuery, C>` impl, and we don't need both. commit 73420fc13bb23151f1baa7199ffa3a38ab955de4 Author: Nicholas Nethercote Date: Fri Oct 6 11:21:33 2023 +1100 Fix a comment. It was duplicated from the method above. commit 449b84cb99203a1eaa735f49958b6ddabc8de779 Author: Nicholas Nethercote Date: Fri Oct 6 11:20:02 2023 +1100 Remove `map_layouts`. As per the `FIXME` comment, it's an abstraction that makes the code harder to read. commit 2c9b0de8ea5f40af06f3c57eb0a1a1d46c20658d Merge: cae0791da47 0aedec4849f Author: bors Date: Fri Oct 6 00:03:56 2023 +0000 Auto merge of #116269 - Veykril:rustc-abi, r=WaffleLapkin Bring back generic parameters for indices in rustc_abi and make it compile on stable This effectively reverses https://github.com/rust-lang/rust/pull/107163, allowing rust-analyzer to depend on this crate again, It also moves some glob imports / expands them in the first commit because they made it more difficult for me to reason about things. commit c8f3aa451a0b50051980cf22d5ca35d7f515b43b Author: Chris Denton Date: Fri Oct 6 00:35:00 2023 +0100 Remove libc We don't use much libc on Windows. commit ad8271dd56bc3a0ef4a1a28af1ef321608d950b2 Author: Nicholas Nethercote Date: Fri Oct 6 10:16:20 2023 +1100 Use `collect` to decode `Vec`. It's hyper-optimized, we don't need our own unsafe code here. This requires getting rid of all the `Allocator` stuff, which isn't needed anyway. commit 1d71971973cd7429e9cf61c27bfb95daaac86486 Author: Nicholas Nethercote Date: Fri Oct 6 10:10:16 2023 +1100 Streamline some `Encodable` impls. Making them consistent with similar impls. commit 2db1d5983032b3f3f80646310c3b39f417a6af2d Author: Nicholas Nethercote Date: Fri Oct 6 10:05:07 2023 +1100 Use `collect` for decoding more collection types. commit 5f69ca62f2ceb9fab475c05e6df426fcc26cb77d Author: Nicholas Nethercote Date: Fri Oct 6 09:50:23 2023 +1100 rustc_serialize: merge `collection_impls.rs` into `serialize.rs`. `serialize.rs` has the `Encodable`/`Decodable` impls for lots of basic types, including `Vec`. `collection_impls` has it for lots of collection types. The distinction isn't really meaningful, and it's simpler to have them all in a single file. commit 409193654d6252a4cfa674588a77668ba653e384 Author: Nicholas Nethercote Date: Fri Oct 6 10:17:29 2023 +1100 Make the comment order match variant declaration order. commit 80bf6883be9af0bee3e764a3cdc0ac73c0cc239a Author: Nicholas Nethercote Date: Fri Oct 6 10:16:54 2023 +1100 Remove an unnecessary `pub(crate)`. commit d464b72970faf5769c6c02d52f21f8e26eb1727d Author: Jason Newcomb Date: Tue Sep 26 23:56:38 2023 -0400 Add more diagnostic items for clippy commit f703475b4eaef5c65a0891a9e27d3945aec4ced6 Author: Nicholas Nethercote Date: Thu Oct 5 20:59:15 2023 +1100 Remove unused serialization support for `LinkedList`. commit 3ee67475b29b8baa288043f2153365efca5f56e9 Author: Nicholas Nethercote Date: Thu Oct 5 20:54:54 2023 +1100 rustc_serialize: Remove unneeded feature decls. I.e. `maybe_uninit_slice` and `new_uninit`. Also sort the remaining features and remove an ugly, low-value comment. commit 1a6ab015d00e36b974ef8bbde0e3b054e96b1e2d Merge: ff3e990e42f 11afb99b4ff Author: bors Date: Thu Oct 5 22:07:09 2023 +0000 Auto merge of #3107 - eduardosm:update-deps, r=RalfJung Update dependencies commit eaafb256f8e729338603476ab1e54b804efead91 Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Replace LocationExtended with DefLocation in SsaLocals commit 4357482bfd9a3cda2fc41e986306fa50d014757d Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Move DefLocation from rustc_codegen_ssa to rustc_middle commit 6c348b77fe24c0834cc2612f62f4ab86faba0651 Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Remove small dominators optimization from SsaLocals The optimization is now part of the general implementation. commit 0528d378b6c526d8e149a2807a71fd316c11ebf0 Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Optimize dominators for small path graphs Generalizes the small dominators approach from #107449. commit ba694e301cfbb7709db159b7b876af9fd18a43c3 Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Remove redundant Dominators::start_node field commit a8ec7ddf0efac856abc71ab0394933afc58a9f26 Author: Tomasz Miąsko Date: Thu Oct 5 00:00:00 2023 +0000 Test immediate dominators using public API commit cbe892fd6598676f1d6efa4024d41ab3e4490598 Author: Ralf Jung Date: Thu Oct 5 21:17:10 2023 +0200 fix fast-path for try_eval_scalar_int commit e825497b7dcd4ea2dfca284d7aac97848becf784 Merge: f1ede97b145 4577c1dc057 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Oct 5 21:47:15 2023 +0200 Merge pull request #1396 from bjorn3/aarch64_asm Support inline asm on AArch64 commit 9facf0bf72acf6cbf6ecb6c28c4b5364efc6b83f Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Oct 5 19:41:41 2023 +0000 Properly export function defined in test which uses global_asm!() Currently the test passes with the LLVM backend as the codegen unit partitioning logic happens to place both the global_asm!() and the function which calls the function defined by the global_asm!() in the same CGU. With the Cranelift backend it breaks however as it will place all assembly in separate codegen units to be passed to an external linker. commit cae0791da47bb01f16885eb233dcd66b0093a6e1 Merge: cdca82c2c85 e30d27be00c Author: bors Date: Thu Oct 5 19:42:05 2023 +0000 Auto merge of #116417 - ouz-a:trait_type_detective, r=compiler-errors Remove is global hack In attempt to fix https://github.com/rust-lang/rust/issues/114057 we found several issues with how compiler computes layouts, this change removes `is_global` from `and` to stop impl from being shadowed. In depth conversation can be read here https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/Getting.20different.20types.20from.20almost.20same.20inputs This is a fix candidate opened for performance run. r? `@lcnr` commit 4577c1dc057685f9418c76d1ccfc2de0210bd0e8 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Oct 5 19:23:40 2023 +0000 Temporarily remove riscv64 inline asm support Riscv support is not currently being tested so it is likely broken. Removing it may avoid confusion in the future. commit b1421dea1d9f99220880413767ea45dfe988c83e Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Oct 5 19:06:08 2023 +0000 Support inline asm on AArch64 Also stop changing the frame pointer on x86_64. This confuses unwinders. commit a47b9fd2e6738b4256b462380504c77f0752e0b7 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Oct 5 18:55:18 2023 +0000 Remove stub support for 32bit inline assembly Cranelift doesn't support any 32bit target yet and this helps with keeping everything in sync. commit e30d27be00c5fd3dda58cbb04013974f978710da Author: Oğuz Ağcayazı Date: Wed Oct 4 14:11:38 2023 +0300 remove is global hack commit 8a1be9942d63f0417efc1ead54dd71ff088140e3 Author: Martin Nordholts Date: Mon Aug 28 08:18:35 2023 +0200 Allow file names to end with '>' The `rustc_span::FileName` enum already differentiates between real files and "fake" files such as ``. We do not need to artificially forbid real file names from ending in `>`. commit cdca82c2c853c8373c0c333a2fd7d1b480d7f1d2 Merge: 3bcad65fbf6 76d0b794cb5 Author: bors Date: Thu Oct 5 17:50:50 2023 +0000 Auto merge of #116455 - matthiaskrgr:rollup-p226a5u, r=matthiaskrgr Rollup of 5 pull requests Successful merges: - #116220 (stabilize `Option::as_`(`mut_`)`slice`) - #116288 (Add Span to various smir types) - #116415 (Move subtyper below reveal_all and change reveal_all) - #116428 (Add a note to duplicate diagnostics) - #116452 (Do not assert that hidden types don't have erased regions.) r? `@ghost` `@rustbot` modify labels: rollup commit 11afb99b4ff378a97abf4f03b0fa2a0ed9a4351e Author: Eduardo Sánchez Muñoz Date: Thu Oct 5 19:30:31 2023 +0200 Update test dependencies commit bbebfa718690ab79c11814bbdbac666f12165daf Author: Eduardo Sánchez Muñoz Date: Thu Oct 5 19:29:27 2023 +0200 Update miri-script dependencies commit f49d325f9dee9d6ad6051d71d160d38cb9f79498 Author: Eduardo Sánchez Muñoz Date: Thu Oct 5 19:29:02 2023 +0200 Update cargo-miri dependencies commit 95c459098868ca9c31f857dac8f085665d593039 Author: Eduardo Sánchez Muñoz Date: Thu Oct 5 19:28:26 2023 +0200 Update miri dependencies commit 76d0b794cb5eb618b13e444b2d28ce59ada01efe Merge: c1c5ab717ef 14c846cb05a Author: Matthias Krüger Date: Thu Oct 5 19:24:35 2023 +0200 Rollup merge of #116452 - cjgillot:noassert-erased, r=oli-obk Do not assert that hidden types don't have erased regions. cc https://github.com/rust-lang/rust/issues/116306 `args` can have erased regions. In the linked issue, this is reached by computing whether a large type is `Freeze` to compute its ABI. I do not have a minimized test to include. commit c1c5ab717efbaf277869616d585aca8de3e47d73 Merge: 08cc7428d9c 5453a9f34d2 Author: Matthias Krüger Date: Thu Oct 5 19:24:35 2023 +0200 Rollup merge of #116428 - Alexendoo:note-duplicate-diagnostics, r=compiler-errors,estebank Add a note to duplicate diagnostics Helps explain why there may be a difference between manual testing and the test suite output and highlights them as something to potentially look into For existing duplicate diagnostics I just blessed them other than a few files that had other `NOTE` annotations in commit 08cc7428d9c681ca5fbd90d0fb70662e9b95d781 Merge: b301bd4220f 3088c4b0466 Author: Matthias Krüger Date: Thu Oct 5 19:24:34 2023 +0200 Rollup merge of #116415 - ouz-a:move_subtyper, r=oli-obk Move subtyper below reveal_all and change reveal_all In previous attempt https://github.com/rust-lang/rust/pull/116378 we tried to handle `Opaque` in few different places, but this isn't necessary, after moving subtyper below reveal_all and calling `super_place` on reveal_all, issues cease to exist. r? ``@oli-obk`` Fixes https://github.com/rust-lang/rust/issues/116332 Fixes https://github.com/rust-lang/rust/issues/116265 Fixes https://github.com/rust-lang/rust/issues/116383 Fixes https://github.com/rust-lang/rust/issues/116333 commit b301bd4220f7b2c755bff334251223678f341b76 Merge: 864e5d8d94e a49138e46e0 Author: Matthias Krüger Date: Thu Oct 5 19:24:34 2023 +0200 Rollup merge of #116288 - ouz-a:smir_spans, r=spastorino Add Span to various smir types Had to make few extra changes to few structs to attach spans to them. r? ``@oli-obk`` commit 864e5d8d94e7a6aa5ed1780ff3846ceae548ee5e Merge: cf9fd95b1c2 702da3b89c8 Author: Matthias Krüger Date: Thu Oct 5 19:24:33 2023 +0200 Rollup merge of #116220 - llogiq:stabilize-option-as-slice, r=BurntSushi stabilize `Option::as_`(`mut_`)`slice` This is the stabilization to #108545. Thanks to everyone who helped getting this into Rust proper. commit 3088c4b0466085a81f83fbe3a10822fac75591b5 Author: ouz-a Date: Tue Oct 3 13:19:00 2023 +0300 move subtyper change reveal_all commit 14c846cb05ae00f6769e00c223b87fd8d43fef28 Author: Camille GILLOT Date: Thu Oct 5 15:50:36 2023 +0000 Do not assert that hidden types don't have erased regions. commit 3bcad65fbf67b6edf87c949531fbc13435882e6b Merge: cf9fd95b1c2 86b031b7349 Author: bors Date: Thu Oct 5 15:24:54 2023 +0000 Auto merge of #103046 - JanBeh:PR_clarify_cmp_terminology, r=workingjubilee docs: Correct terminology in std::cmp This PR is the result of some discussions on URLO: * [Traits in `std::cmp` and mathematical terminology](https://users.rust-lang.org/t/traits-in-std-cmp-and-mathematical-terminology/69887) * [Are poker hands `Ord` or `PartialOrd`?](https://users.rust-lang.org/t/are-poker-hands-ord-or-partialord/82644) Arguably, the documentation currently isn't very precise regarding mathematical terminology. This can lead to misunderstandings of what `PartialEq`, `Eq`, `PartialOrd`, and `Ord` actually do. While I believe this PR doesn't give any new API guarantees, it expliclitly mentions that `PartialEq::eq(a, b)` may return `true` for two distinct values `a` and `b` (i.e. where `a` and `b` are not equal in the mathematical sense). This leads to the consequence that `Ord` may describe a weak ordering instead of a total ordering. In either case, I believe this PR should be thoroughly reviewed, ideally by someone with mathematical background to make sure the terminology is correct now, and also to ensure that no unwanted new API guarantees are made. In particular, the following problems are addressed: * Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of `Ord` in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. * ~~Added a section "Weak orders" to explain that `Ord` may also describe a weak order or total preorder, depending on how `PartialEq::eq` has been implemented.~~ (Removed, see [comment](https://github.com/rust-lang/rust/pull/103046#issuecomment-1279929676)) * Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`. commit 098dd979393e596a4434f5b88492054452b6b814 Author: Jakub Beránek Date: Thu Oct 5 16:09:52 2023 +0200 Remove `try-merge` from CI workflow commit f6017250f83126193bcc7e93a3764bbed05f3f46 Author: Jakub Beránek Date: Thu Oct 5 16:02:03 2023 +0200 Enable new bors try branch to run on CI commit cf9fd95b1c278da6069546f305925e6250b19842 Merge: 90f3a6f920d 40a52cf55cc Author: bors Date: Thu Oct 5 13:35:18 2023 +0000 Auto merge of #114042 - liushuyu:ubuntu/i586-fpmath, r=workingjubilee core library: Disable fpmath tests for i586 ... This patch disables the floating-point epsilon test for i586 since x87 registers are too imprecise and can't produce the expected results. commit 86b031b7349594f23084c0599177975c47eb9925 Author: Jan Behrens Date: Wed Jul 26 19:36:26 2023 +0200 docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`. commit 90f3a6f920df62c02c52b6a2c0e9e43aa029a778 Merge: 5c3a0e932b7 c953b6c0147 Author: bors Date: Thu Oct 5 11:46:55 2023 +0000 Auto merge of #104153 - tspiteri:doc-float-constants, r=workingjubilee doc: expand description for f32 and f64 associated constants This explains the meaning of some of the floating-point associated constants. commit 5c3a0e932b7c6864f98dac739b576e9ff5913739 Merge: e2939270168 e63d19c4dda Author: bors Date: Thu Oct 5 09:59:14 2023 +0000 Auto merge of #116427 - cjgillot:no-internal, r=oli-obk Remove mir::LocalDecl::internal. It does not serve any purpose, as we don't have typeck-based generator witnesses any more. commit 81d1f7ea9d86490de2920d7b726db412c21de005 Author: Nicholas Nethercote Date: Thu Oct 5 19:56:19 2023 +1100 Use a closure when setting `State::Active`. commit a49138e46e09a019ecf26077a488cf579bd1a135 Author: Oğuz Ağcayazı Date: Thu Oct 5 11:13:05 2023 +0300 impl stable for kinds commit a79567b01c0b5000025896a191b709e422f4923f Author: ouz-a Date: Sat Sep 30 17:18:31 2023 +0300 add span to statements commit e2939270168f2a23ef2ec0b2a193dbb63f92ae07 Merge: 5236c8e1fa2 4a14a80605d Author: bors Date: Thu Oct 5 08:12:55 2023 +0000 Auto merge of #116443 - workingjubilee:rollup-r9mh13f, r=workingjubilee Rollup of 5 pull requests Successful merges: - #116223 (Fix misuses of a vs an) - #116296 (More accurately point to where default return type should go) - #116429 (Diagnostics: Be more careful when suggesting struct fields) - #116431 (Tweak wording of E0562) - #116432 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 2)) r? `@ghost` `@rustbot` modify labels: rollup commit 4a14a80605dd187e46badc24c6fda4120d915b0c Merge: d7b02c3d409 a46ccd8d3f4 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:31 2023 -0700 Rollup merge of #116432 - notriddle:master, r=fmease rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 2) Follow up https://github.com/rust-lang/rust/pull/116214 commit d7b02c3d409ca2481e8a04e37d40163396f31227 Merge: a9a389cf444 041e54bd92a Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:30 2023 -0700 Rollup merge of #116431 - estebank:issue-80476, r=compiler-errors Tweak wording of E0562 Fix #80476. commit a9a389cf44451f71530b21daf5f125decc9dfdf6 Merge: cfce3a919dc 867cc41b5b2 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:30 2023 -0700 Rollup merge of #116429 - fmease:clean-up-struct-field-suggs, r=compiler-errors Diagnostics: Be more careful when suggesting struct fields Consolidate the various places which filter out struct fields that shouldn't be suggested into a single function. Previously, each of those code paths had slightly different and incomplete metrics for no good reason. Now, there's only a single 'complete' metric (namely `is_field_suggestable`) which also filters out hygienic fields that come from different syntax contexts. Fixes #116334. commit ed900871cfc92d14a6ddc7acd91093942caa6253 Merge: 673f4473535 f61b14dfc25 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:29 2023 -0700 Rollup merge of #116223 - catandcoder:master, r=cjgillot Fix misuses of a vs an Fixes the misuse of "a" vs "an", according to English grammatical expectations and using https://www.a-or-an.com/ commit cfce3a919dc09b41ba522202c0bffa9b8191bc57 Merge: ea3454eabb6 dd5f26c42db Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:29 2023 -0700 Rollup merge of #116296 - compiler-errors:default-return, r=estebank More accurately point to where default return type should go When getting the "default return type" span, instead of pointing to the low span of the next token, point to the high span of the previous token. This: 1. Makes forming return type suggestions more uniform, since we expect them all in the same place. 2. Arguably makes labels easier to understand, since we're pointing to where the implicit `-> ()` would've gone, rather than the starting brace or the semicolon. r? ```@estebank``` commit ea3454eabb6ac1ac4c0fb1326e72b4f19505b0b8 Merge: 5236c8e1fa2 f44d116e1f9 Author: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Thu Oct 5 00:56:29 2023 -0700 Rollup merge of #116223 - catandcoder:master, r=cjgillot Fix misuses of a vs an Fixes the misuse of "a" vs "an", according to English grammatical expectations and using https://www.a-or-an.com/ commit ff3e990e42ff9e7fa01fd4f85cb06c5fa23b4d35 Merge: 6ed502d0127 5178ae60a1c Author: bors Date: Thu Oct 5 07:06:54 2023 +0000 Auto merge of #3106 - RalfJung:tree-borrows-initial, r=RalfJung Tree Borrows: do not create new tags as 'Active' Cc `@Vanille-N` commit 9d4e49b386c66520eb6434405a86ef56614d84bc Author: Nicholas Nethercote Date: Thu Oct 5 16:35:50 2023 +1100 Use `declared_features` to avoid two lookups. commit 56fd2531ac44f95295f78b9f55383bfebc26d358 Author: Nicholas Nethercote Date: Thu Oct 5 16:33:42 2023 +1100 Add two setter functions to `Features`. commit 95d1aa075f1bdd7acf1b0c0f0b918b3371cf987d Author: Nicholas Nethercote Date: Thu Oct 5 16:24:31 2023 +1100 Record all declared features. Currently `rust_20XX_preview` features aren't recorded as declared even when they are explicit declared. Similarly, redundant edition-dependent features (e.g. `test_2018_feature`) aren't recorded as declared. This commit marks them as recorded. There is no detectable functional change, but it makes things more consistent. commit eb209057b1c7a1e7852793e8f53eadfc9d839b2c Author: Nicholas Nethercote Date: Thu Oct 5 16:20:07 2023 +1100 Rename `Resolver::active_features`. For the reasons described in the previous commit. commit 4602d9257de0939ff8770dcf7f10ac1832bce35f Author: Nicholas Nethercote Date: Thu Oct 5 16:08:07 2023 +1100 Rename `Features::active_features`. The word "active" is currently used in two different and confusing ways: - `ACTIVE_FEATURES` actually means "available unstable features" - `Features::active_features` actually means "features declared in the crate's code", which can include feature within `ACTIVE_FEATURES` but also others. (This is also distinct from "enabled" features which includes declared features but also some edition-specific features automatically enabled depending on the edition in use.) This commit changes the `Features::active_features` to `Features::declared_features` which actually matches its meaning. Likewise, `Features::active` becomes `Features::declared`. commit b229be0127dacde928826f6dac697230c74eef05 Author: Nicholas Nethercote Date: Thu Oct 5 12:38:02 2023 +1100 Overhaul `config::features`. The new way of doing things: - Avoids some code duplication. - Distinguishes the `crate_edition` (which comes from `--edition`) and the `features_edition` (which combines `--edition` along with any `rustc_20XX_preview` features), which is useful. - Has a simpler initial loop, one that just looks for `rustc_20XX_preview` features in order to compute `features_edition`. - Creates a fallible alternative to `Features::enabled`, which is useful. It's not easy to see how exactly the old and new code are equivalent, but it's reassuring to know that the test coverage is quite good for this stuff. commit 5178ae60a1c7156d994a66bdc488f386c2234f5d Author: Ralf Jung Date: Thu Oct 5 08:18:50 2023 +0200 Tree Borrows: do not create new tags as 'Active' commit 6ed502d0127cc739a5f4a2a1ca4eb6f53341a2c5 Merge: 40c928e9463 31a57557f6f Author: bors Date: Thu Oct 5 06:07:27 2023 +0000 Auto merge of #3000 - RalfJung:no_std, r=oli-obk auto-detect no_std where possible r? `@oli-obk` Cc https://rust-lang.zulipchat.com/#narrow/stream/269128-miri/topic/restricted_std.20sysroot.3F commit 5236c8e1fa25c45f11f02ae72fc27f64d86ba606 Merge: b7816453329 06d9602d331 Author: bors Date: Thu Oct 5 03:00:30 2023 +0000 Auto merge of #116273 - compiler-errors:refine2, r=tmandry Only trigger `refining_impl_trait` lint on reachable traits Public but unreachable traits don't matter 😸 r? `@tmandry` commit b781645332971d028d1d17c475fa2c40919132ba Merge: afe67fa2ef1 2f5249019e9 Author: bors Date: Thu Oct 5 01:14:25 2023 +0000 Auto merge of #116184 - compiler-errors:afit-lint, r=tmandry Add `async_fn_in_trait` lint cc https://github.com/rust-lang/rust/pull/115822#issuecomment-1731168465 Mostly unsure what the messaging should be. Feedback required. r? `@tmandry` commit 5453a9f34d21bdd1031d58b68fcd6a92adc82108 Author: Alex Macleod Date: Wed Oct 4 18:34:50 2023 +0000 Add a note to duplicate diagnostics commit 8ba91378401f5483b1d834be33911028507a9d5d Author: Nicholas Nethercote Date: Thu Oct 5 11:38:43 2023 +1100 Merge `STABLE_REMOVED_FEATURES` list into `REMOVED_FEATURES`. There is a single features (`no_stack_check`) in `STABLE_REMOVED_FEATURES`. But the treatment of `STABLE_REMOVED_FEATURES` and `REMOVED_FEATURES` is actually identical. So this commit just merges them, and uses a comment to record `no_stack_check`'s unique "stable removed" status. This also lets `State::Stabilized` (which was a terrible name) be removed. commit 5d9559e0269d9d7db06c825d56d475757232c924 Author: Nicholas Nethercote Date: Thu Oct 5 11:18:51 2023 +1100 Inline and remove `feature_removed` function. It has a single call site. This increases consistency because other errors within `features` are emitted directly. commit 9e2cd038b03c8194a68e30dd823d145f1f0d4806 Author: Nicholas Nethercote Date: Thu Oct 5 11:15:14 2023 +1100 Factor out some repeated feature-getting code. commit e24f39440478dcddddb83b9999aa724d4a093d8f Author: Nicholas Nethercote Date: Thu Oct 5 10:17:42 2023 +1100 Add comments to `config::features`. I found this function very confusing, and it took me quite some time to work out what it was doing. These comments capture that hard-earned knowledge. commit 1ddb2872ddeb5d56f7bdecfd4175fb13fc510069 Author: Nicholas Nethercote Date: Wed Oct 4 14:54:12 2023 +1100 Streamline `find_lang_feature_issue`. It currently processes `ACTIVE_FEATURES` separately from `ACCEPTED_FEATURES`, `REMOVED_FEATURES`, and `STABLE_REMOVED_FEATURES`, for no good reason. This commit treats them uniformly. commit 3c1b60c1b44b7a6e322982c5e19c0dc5e628680c Author: Nicholas Nethercote Date: Wed Oct 4 10:00:30 2023 +1100 Split `declare_features!`. It's a macro with four clauses, three of which are doing one thing, and the fourth is doing something completely different. This commit splits it into two macros, which is more sensible. commit 043a9873b9ca6671744cf29c5cd0fe04c54e9032 Author: Nicholas Nethercote Date: Wed Oct 4 10:06:17 2023 +1100 Remove `set!` macro. It has a single call site. commit 53fe37de2e11537bf2953a29df3c5be8a8858850 Author: Nicholas Nethercote Date: Wed Oct 4 09:51:03 2023 +1100 Remove unused `Span` from the `set` function in `State::Active`. commit afe67fa2ef1bb0dcf9077d55cdd1c64a9969c9cf Merge: 2bbb6198933 a2051dd578f Author: bors Date: Wed Oct 4 22:32:46 2023 +0000 Auto merge of #116370 - nnethercote:more-arena-stuff, r=cjgillot Remove the `TypedArena::alloc_from_iter` specialization. It was added in #78569. It's complicated and doesn't actually help performance. r? `@cjgillot` commit 2f5249019e94f99920dae6df832bde633b151eb4 Author: Tyler Mandry Date: Wed Oct 4 18:20:05 2023 -0400 Apply suggestions from code review Co-authored-by: Travis Cross commit c5c6d703de74e1965871c220d35ec40ce40b0b43 Author: Michael Goulet Date: Mon Oct 2 21:39:07 2023 +0000 Point to closure return instead of output if defaulted commit dd5f26c42dbe24491cc2aae12bca747d1701936c Author: Michael Goulet Date: Wed Oct 4 21:09:50 2023 +0000 Fix spans for comments in rustfmt commit 56794fa5f1a508ed0cf1b3f44bb152b3c0c641f1 Author: Michael Goulet Date: Mon Oct 2 21:24:23 2023 +0000 Fix clippy commit 1f079cfb440c05578fce656999d363d916500850 Author: Michael Goulet Date: Mon Oct 2 21:39:07 2023 +0000 Point to closure return instead of output if defaulted commit 89b14ae212e50f7a92800c4cb4f7cdefd2b1495e Author: Michael Goulet Date: Mon Oct 2 21:24:23 2023 +0000 Fix clippy commit 137b6d0b01e880b8a8163cd7a14141afc080a9ee Author: Michael Goulet Date: Sat Sep 30 19:29:41 2023 +0000 Point to where missing return type should go commit 2bbb6198933abf193c0ef1d18d9d70f99eed59ba Merge: eea26141ec2 bf4df0617fa Author: bors Date: Wed Oct 4 20:44:38 2023 +0000 Auto merge of #114417 - chinedufn:fix-expect-unused-in-impl-block-rust-issue-114416, r=cjgillot Fix multiple `expect` attribs in impl block Closes #114416 commit 40c928e94638fdfbafe3e87a058f7cbf8615b311 Merge: 4f73d3fc72a 7d065db5c11 Author: bors Date: Wed Oct 4 20:19:16 2023 +0000 Auto merge of #3105 - RalfJung:sysroot-target, r=RalfJung miri-script: print which sysroot target we are building commit 7d065db5c118af4d77960ec047c4b2b39eaa0065 Author: Ralf Jung Date: Wed Oct 4 22:17:15 2023 +0200 miri-script: print which sysroot target we are building commit 31a57557f6fc9319ef8cb8f18ad1f22690d92d39 Author: Ralf Jung Date: Wed Oct 4 22:11:15 2023 +0200 auto-detect no_std where possible commit e46236cceb03a5f58cae91b9d8a1b18040443b5c Author: Urgau Date: Wed Oct 4 16:03:39 2023 +0200 Clarify `invalid_reference_casting` lint around interior mutable types commit a46ccd8d3f4813d6f0d3422040898f41eaae0e8d Author: Michael Howell Date: Wed Oct 4 13:04:45 2023 -0700 Add URL to test case issues commit 9266270ef55e3138de0c58b9cd4c0949aa2eb04c Author: Michael Howell Date: Wed Oct 4 12:58:06 2023 -0700 Rename issue-\d+.rs tests to have meaningful names commit 041e54bd92abaadc8c26a619976f76a77d022a39 Author: Esteban Küber Date: Wed Oct 4 19:51:43 2023 +0000 Tweak wording of E0562 Fix #80476. commit 867cc41b5b2f0e84de6a1fd10099e9383cecc807 Author: León Orell Valerian Liehr Date: Wed Oct 4 19:10:35 2023 +0200 clean up struct field suggestions commit a198aff4a4b1b83476497438cfc4771fb19c7bc4 Author: Michael Howell Date: Wed Oct 4 12:08:47 2023 -0700 Add `crate_name` to test so that it can be renamed commit 8d92c996caa8fa1c3e504be5049742b8e6403f67 Author: Esteban Küber Date: Wed Oct 4 18:58:06 2023 +0000 Fix test on WASM target by making ambiguity pruning more agressive commit eea26141ec2bf07a825011af841463dec51a04c9 Merge: f306362fb97 abece4faccb Author: bors Date: Wed Oct 4 18:54:49 2023 +0000 Auto merge of #115200 - rcvalle:rust-cfi-fix-115199, r=workingjubilee Disable CFI for core and std CFI violations Work around https://github.com/rust-lang/rust/issues/115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature. commit e63d19c4ddae8f7ce51e1953bfc4a61235f528f7 Author: Camille GILLOT Date: Wed Oct 4 17:50:03 2023 +0000 Remove mir::LocalDecl::internal. commit abece4faccbeb2f0985415e279bbc79ecc2c1380 Author: Ramon de C Valle Date: Thu Aug 24 17:12:54 2023 -0700 Update documentation for LLVM CFI support Updates documentation for LLVM CFI support with recommended information since the user can now rebuild and use both core and std with CFI enabled using the Cargo build-std feature. commit 7b45674015312635264514669bd1d44f13b750c1 Author: Ramon de C Valle Date: Thu Aug 24 17:09:15 2023 -0700 Disable CFI for core and std CFI violations Works around #115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature. commit f306362fb97fadcee44f68817a1d22292458138b Merge: 2ffeb4636b4 0ece171c2f7 Author: bors Date: Wed Oct 4 16:51:42 2023 +0000 Auto merge of #116413 - nnethercote:rm-E0551, r=compiler-errors Remove E0551 Because it's the same as E0539. Fixes #51489. r? `@Nilstrieb` commit 23efab4811c44e315ffd0322c69cbcbc3125eddf Author: Ikko Eltociear Ashimine Date: Thu Oct 5 00:03:04 2023 +0900 Fix typo in attrs.rs documenation -> documentation commit 2ffeb4636b4ae376f716dc4378a7efb37632dc2d Merge: 65519f5fc0b c0a42cc7bdc Author: bors Date: Wed Oct 4 14:17:57 2023 +0000 Auto merge of #116381 - Mark-Simulacrum:drop-wasm32-unknown-emscripten, r=Kobzol Remove wasm32-unknown-emscripten tests from CI This builder tested the wasm32-unknown-emscripten target, which is tier 2 (and so not eligible for testing). In the recent beta [promotion](https://github.com/rust-lang/rust/pull/116362#issuecomment-1744960904), we ran into a problem with this target: emscripten doesn't support passing environment variables into the std environment, so we can't enable RUSTC_BOOTSTRAP for libtest in order to pass -Zunstable-options. We worked around this for the beta/stable branches, but given this problem, and its tier 2 status, just dropping the target's tests entirely seems warranted. Downgrading to tier 3 may also be a good idea, but that is a separate conversation not proposed here. commit 9554e477c29e6ddca9e5cdce71524341ef9d48e8 Merge: b437069f597 404217e6312 Author: bors Date: Wed Oct 4 14:12:50 2023 +0000 Auto merge of #11605 - xFrednet:changelog-1-73, r=blyxyas Changelog for Rust 1.73 🖊️ Roses are red, violets are blue, I'm tired... :zzz: Oh nice, tea :tea: --- ### The cat of this release: ![cat-like-doritos](https://github.com/rust-lang/rust-clippy/assets/114838443/1ca9eb1e-3e5c-42a4-bda9-6f24a2e03015) cc: `@Centri3` & `@blyxyas` As the author, I call dibs on the 1.74 cat picture :cat2: --- changelog: none commit e53c7787772679918e55106a8b22bee1b92b8b57 Author: Jakub Beránek Date: Wed Oct 4 12:57:46 2023 +0200 Bump host compiler on x64 dist Linux to LLVM 17.0.2 commit 65519f5fc0bcd8a47e547226bbc7498a2b9a59fb Merge: 9fbd593a563 2934fe07b7f Author: bors Date: Wed Oct 4 09:55:02 2023 +0000 Auto merge of #116360 - compiler-errors:async-span, r=oli-obk Point to full `async fn` for future Semi-follow-up to https://github.com/rust-lang/rust/pull/116296#discussion_r1342007575 cc `@asquared31415` commit 716f211030ff4f251a31624d453fdc013e43b210 Merge: f107a50b233 2c525fd7589 Author: bors Date: Wed Oct 4 09:55:02 2023 +0000 Auto merge of #116360 - compiler-errors:async-span, r=oli-obk Point to full `async fn` for future Semi-follow-up to https://github.com/rust-lang/rust/pull/116296#discussion_r1342007575 cc `@asquared31415` commit 0aedec4849f7fdac2a36c06fc99653e0540e198e Author: Lukas Wirth Date: Fri Sep 29 20:34:46 2023 +0200 Remove unnecessary features from rustc_abi commit 404217e631270d9a167cf63cbb3ea50cbe370ebc Author: xFrednet Date: Wed Oct 4 10:28:52 2023 +0200 Address PR Review <3 commit 9fbd593a56387354ea44a72f45f4df1850704f5f Merge: dd513e11505 76b70eb0337 Author: bors Date: Wed Oct 4 07:46:03 2023 +0000 Auto merge of #116353 - Kobzol:new-bors-event, r=Mark-Simulacrum Add new bors try branches to CI Workflows for the new bors weren't launching, because its branches weren't whitelisted here. r? `@Mark-Simulacrum` commit 0ece171c2f7f96ca9bd445fbac3c1b0c4402af14 Author: Nicholas Nethercote Date: Wed Oct 4 17:20:15 2023 +1100 Remove E0551. Because it's the same as E0539. Fixes #51489. commit 81136cb391135e7a2817316268f0795e7350f5ea Author: Nicholas Nethercote Date: Wed Oct 4 16:21:02 2023 +1100 Sort `compiler/rustc_attr/Cargo.toml` dependencies. It's easier to read in sorted order. commit dd513e1150569d2c5605bcdd4b2a6741deea3294 Merge: a7bb2f67bf8 d4370cc00c6 Author: bors Date: Wed Oct 4 05:29:56 2023 +0000 Auto merge of #116406 - weihanglo:update-cargo, r=weihanglo Update cargo 9 commits in 59596f0f31a94fde48b5aa7e945cd0b7ceca9620..794d0a82547f3081044c0aca7b6083733ce51344 2023-09-29 19:29:17 +0000 to 2023-10-03 23:19:33 +0000 - Prep for automating MSRV management (rust-lang/cargo#12767) - chore(deps): update rust crate itertools to 0.11.0 (rust-lang/cargo#12759) - fix bug: corruption when cargo killed while writing (rust-lang/cargo#12744) - Disable custom_target::custom_bin_target on windows-gnu (rust-lang/cargo#12763) - chore(deps): update compatible (rust-lang/cargo#12757) - Add more missing `strip` info to docs. (rust-lang/cargo#12754) - chore(deps): update actions/checkout action to v4 (rust-lang/cargo#12762) - chore(deps): update rust crate cargo_metadata to 0.18.0 (rust-lang/cargo#12758) - fix(test): Add back in newlines to diffs (rust-lang/cargo#12753) r? ghost commit a7bb2f67bf8f868401ba90bc0f5b9dc75d1dfe0b Merge: 4910642aab5 d4940488a6a Author: bors Date: Wed Oct 4 03:38:42 2023 +0000 Auto merge of #116408 - matthiaskrgr:rollup-hmolg4m, r=matthiaskrgr Rollup of 7 pull requests Successful merges: - #115961 (Replace 'mutex' with 'lock' in RwLock documentation) - #116146 (Clarify `arg` and `args` documentation) - #116363 (Adapt `todo!` documentation to mention displaying custom values) - #116365 (bootstrap: make copying linker binaries conditional) - #116388 (rustdoc: fix & clean up handling of cross-crate higher-ranked parameters) - #116393 (Emit feature gate *warning* for `auto` traits pre-expansion) - #116395 (Mark myself as vacation or whatever) r? `@ghost` `@rustbot` modify labels: rollup commit d4940488a6ae450aef6691e596c2bb102f8cb1fd Merge: 4ed2291624d a18729c496b Author: Matthias Krüger Date: Wed Oct 4 05:02:07 2023 +0200 Rollup merge of #116395 - WaffleLapkin:vacationize-waffle, r=lqd Mark myself as vacation or whatever I think I have the capacity to review PRs currently assigned to me, before vacation, but I won't be able to take any more. So, until everything settles down, I don't want to be assigned to new PRs. commit 4ed2291624d227b105754a87a5f74cd9f884839e Merge: 3e293634e2e 7815641be07 Author: Matthias Krüger Date: Wed Oct 4 05:02:07 2023 +0200 Rollup merge of #116393 - compiler-errors:auto-bad, r=WaffleLapkin Emit feature gate *warning* for `auto` traits pre-expansion Auto traits were introduced before we were more careful about not stabilizing new syntax pre-expansion. This is a more conservative step in the general direction we want to go in https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Removal.20of.20.60auto.20trait.60.20syntax. Fixes #116121 commit 3e293634e2e500153d5d8b4b609539b69af9951d Merge: e6a9bb11fbc ace85f0ae31 Author: Matthias Krüger Date: Wed Oct 4 05:02:06 2023 +0200 Rollup merge of #116388 - fmease:rustdoc-fix-n-clean-up-x-crate-higher-ranked-params, r=notriddle rustdoc: fix & clean up handling of cross-crate higher-ranked parameters Preparatory work for the refactoring planned in #113015 (for correctness & maintainability). --- 1. Render the higher-ranked parameters of cross-crate function pointer types **(*)**. 2. Replace occurrences of `collect_referenced_late_bound_regions()` (CRLBR) with `bound_vars()`. The former is quite problematic and the use of the latter allows us to yank a lot of hacky code **(†)** as you can tell from the diff! :) 3. Add support for cross-crate higher-ranked types (`#![feature(non_lifetime_binders)]`). We were previously ICE'ing on them (see `inline_cross/non_lifetime_binders.rs`). --- **(*)**: Extracted from test `inline_cross/fn-type.rs`: ```diff - fn(_: &'z fn(_: &'b str), _: &'a ()) -> &'a () + for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a () ``` **(†)**: It returns an `FxHashSet` which isn't *predictable* or *stable* wrt. source code (`.rmeta`) changes. To elaborate, the ordering of late-bound regions doesn't necessarily reflect the ordering found in the source code. It does seem to be stable across compilations but modifying the source code of the to-be-documented crates (like adding or renaming items) may result in a different order:
Example Let's assume that we're documenting the cross-crate re-export of `produce` from the code below. On `master`, rustdoc would render the list of binders as `for<'x, 'y, 'z>`. However, once you add back the functions `a`–`l`, it would be rendered as `for<'z, 'y, 'x>` (reverse order)! Results may vary. `bound_vars()` fixes this as it returns them in source order. ```rs // pub fn a() {} // pub fn b() {} // pub fn c() {} // pub fn d() {} // pub fn e() {} // pub fn f() {} // pub fn g() {} // pub fn h() {} // pub fn i() {} // pub fn j() {} // pub fn k() {} // pub fn l() {} pub fn produce() -> impl for<'x, 'y, 'z> Trait<'z, 'y, 'x> {} pub trait Trait<'a, 'b, 'c> {} impl Trait<'_, '_, '_> for () {} ```
Further, as the name suggests, CRLBR only collects *referenced* regions and thus we drop unused binders. `bound_vars()` contains unused binders on the other hand. Let's stay closer to the source where possible and keep unused binders. Lastly, using `bound_vars()` allows us to get rid of * the deduplication and alphabetical sorting hack in `simplify.rs` * the weird field `bound_params` on `EqPredicate` both of which were introduced by me in #102707 back when I didn't know better. To illustrate, let's look at the cross-crate bound `T: for<'a, 'b> Trait = (), B<'b> = ()>`. * With CRLBR + `EqPredicate.bound_params`, *before* bounds simplification we would have the bounds `T: Trait`, `for<'a> ::A<'a> == ()` and `for<'b> ::B<'b> == ()` which required us to merge `for<>`, `for<'a>` and `for<'b>` into `for<'a, 'b>` in a deterministic manner and without introducing duplicate binders. * With `bound_vars()`, we now have the bounds `for<'a, b> T: Trait`, `::A<'a> == ()` and `::B<'b> == ()` before bound simplification similar to rustc itself. This obviously no longer requires any funny merging of `for<>`s. On top of that `for<'a, 'b>` is guaranteed to be in source order. commit e6a9bb11fbc500d35d78f330728acfb892f95696 Merge: 0363cc561d2 f55c8796692 Author: Matthias Krüger Date: Wed Oct 4 05:02:06 2023 +0200 Rollup merge of #116365 - P1n3appl3:master, r=onur-ozkan bootstrap: make copying linker binaries conditional The change in #116276 breaks bootstrapping if you don't use `lld` for linking with your stage0 compiler. Making this copy conditional should be enough to fix it. commit 0363cc561d213ea06f8f5a541c1c60a8984d2a5d Merge: d5bd019645a 0c6d279728b Author: Matthias Krüger Date: Wed Oct 4 05:02:04 2023 +0200 Rollup merge of #116363 - Colonial-Dev:issue-116130-fix, r=thomcc Adapt `todo!` documentation to mention displaying custom values Resolves #116130. I copied from the [existing documentation](https://doc.rust-lang.org/std/macro.unimplemented.html) for `unimplemented!` more or less directly, down to the example trait used. I also took the liberty of fixing some formatting and typographical errors that I noticed. commit d5bd019645a49eb200b5a48de11e0b51f9239eb0 Merge: 36e234a0fa4 221d0a661ae Author: Matthias Krüger Date: Wed Oct 4 05:02:04 2023 +0200 Rollup merge of #116146 - Milo123459:milo/clarify-arg-documentation, r=thomcc Clarify `arg` and `args` documentation Fixes #95400 commit 36e234a0fa4a97b9c990909032b25d1494439639 Merge: 79f38b79147 cdf25c904e7 Author: Matthias Krüger Date: Wed Oct 4 05:02:03 2023 +0200 Rollup merge of #115961 - Kriskras99:master, r=thomcc Replace 'mutex' with 'lock' in RwLock documentation When copying the documentation for `clear_poison` from Mutex, not every occurence of 'mutex' was replaced with 'lock'. commit d4370cc00c6b437a9f1f3195adb1dc37f43e573f Author: Weihang Lo Date: Wed Oct 4 10:33:52 2023 +0800 Update cargo commit fd3804ab500dcde3a98c55339c3d36a3dd2c3516 Author: Esteban Küber Date: Thu Sep 28 18:04:54 2023 +0000 Split `traits::error_reporting` to keep files smaller commit 4a0c676791735d6ec4f970e91e120e4810f5c136 Author: Esteban Küber Date: Mon Aug 14 22:02:12 2023 +0000 Update docs for E0282 and E0283, as E0282 now doesn't trigger for `collect` commit 7313c1077455831135776bb7ad1cf76b3268c924 Author: Esteban Küber Date: Mon Aug 14 13:26:11 2023 +0000 Show suggestion for `::assoc_fn` in more cases and fmt code commit 91b9ffeab0f8c491c81cd976c0d23d947cd6d12f Author: Esteban Küber Date: Mon Aug 14 13:09:53 2023 +0000 Reorder fullfillment errors to keep more interesting ones first In `report_fullfillment_errors` push back `T: Sized`, `T: WellFormed` and coercion errors to the end of the list. The pre-existing deduplication logic eliminates redundant errors better that way, keeping the resulting output with fewer errors than before, while also having more detail. commit 2817ece19c67a182c0b0aae402c0e57c8ed22dab Author: Esteban Küber Date: Mon Aug 14 11:56:23 2023 +0000 Show more information when multiple `impl` apply commit 4910642aab5c6230dfbf0cafb382700ed3001dab Merge: 79f38b79147 92c9bcdff46 Author: bors Date: Wed Oct 4 01:49:24 2023 +0000 Auto merge of #116386 - elichai:patch-2, r=thomcc Add missing inline attributes to Duration trait impls Currently `Duration::checked_add` is marked `#[inline]` but it's trait relative `Add::add` is not. Leading to a case where: ```rust pub fn foo() -> Duration { Duration::from_secs(10) + Duration::from_millis(6) } pub fn bar() -> Duration { Duration::from_secs(10).checked_add(Duration::from_millis(6)).expect("overflow when adding durations") } ``` compiles to: ```asm playground::foo: movl $10, %edi xorl %esi, %esi xorl %edx, %edx movl $6000000, %ecx jmpq *::add@GOTPCREL(%rip) playground::bar: movl $10, %eax movl $6000000, %edx retq ``` (The same happens for all arithmetic operation) commit 8fd345dd4b85b6758896995beb5b0417efd52364 Author: Esteban Küber Date: Wed Oct 4 01:35:07 2023 +0000 review comments commit 79f38b79147a5fb3c52d1fd1afc571226a77419c Merge: 187b8131d4f f8fc0d77162 Author: bors Date: Wed Oct 4 00:03:54 2023 +0000 Auto merge of #116367 - scottmcm:more-addr-eq, r=workingjubilee Use `addr_eq` in `{Arc,Rc}::ptr_eq` Since it's made for stuff like this (see #106447) commit f61b14dfc2590ed864e194c121a26e39e995fd02 Author: cui fliter Date: Thu Sep 28 16:15:41 2023 +0800 Fix misuses of a vs an Signed-off-by: cui fliter commit f44d116e1f9a513b8730c1629bf17592bcd9784a Author: cui fliter Date: Thu Sep 28 16:15:41 2023 +0800 Fix misuses of a vs an Signed-off-by: cui fliter commit 948355586fe325acb97be312e9f3c7ef8f13bba7 Author: xFrednet Date: Wed Oct 4 01:19:38 2023 +0200 sudo CI=green commit 8d920a8b0336a59dcb91dda88a309b244bc5fb02 Author: xFrednet Date: Wed Oct 4 00:57:12 2023 +0200 Changelog for Rust 1.73 :pen: commit eab0a75ff942598a57c93f78000a8a9dbb3af9b7 Author: xFrednet Date: Wed Oct 4 01:04:00 2023 +0200 Update version attribute for 1.73 lints commit 18ec4e9bcd7ac13e51c521c9be127e98bdb58faf Author: Esteban Küber Date: Tue Oct 3 21:31:10 2023 +0000 Move some tests around commit 745c1ea4388864d6a832aeacb9fc3b9db1ab9c2f Author: Esteban Küber Date: Tue Oct 3 21:21:02 2023 +0000 Detect missing `=>` after match guard during parsing ``` error: expected one of `,`, `:`, or `}`, found `.` --> $DIR/missing-fat-arrow.rs:25:14 | LL | Some(a) if a.value == b { | - while parsing this struct LL | a.value = 1; | -^ expected one of `,`, `:`, or `}` | | | while parsing this struct field | help: try naming a field | LL | a: a.value = 1; | ++ help: you might have meant to start a match arm after the match guard | LL | Some(a) if a.value == b => { | ++ ``` Fix #78585. commit 187b8131d4f760f856b214fce34534903276f2ef Merge: 36aab8df0ab adb22b92dd3 Author: bors Date: Tue Oct 3 20:35:38 2023 +0000 Auto merge of #105394 - Patiga:improve-udpsocket-docs, r=workingjubilee Improve UdpSocket documentation I tried working with `UdpSocket` and ran into `EINVAL` errors with no clear indication of what causes the error. Also, it was uncharacteristically hard to figure this module out, compared to other Rust `std` modules. 1. `send` and `send_to` return a `usize` This one is just clarity. Usually, returned `usize`s indicate that the buffer might have only been sent partially. This is not the case with UDP. Since that `usize` must always be `buffer.len()`, I have documented that. 2. `bind` limits `connect` and `send_to` When you bind to a limited address space like localhost, you can only `connect` to addresses in that same address space. Error kind: `AddrNotAvailable`. 3. `connect`ing to localhost locks you to localhost On Linux, if you first `connect` to localhost, subsequent `connect`s to non-localhost addresses fail. Error kind: `InvalidInput`. For debugging the third one, it was really hard to find someone else who already had that problem. I only managed to find this thread: https://www.mail-archive.com/netdev@vger.kernel.org/msg159519.html commit a18729c496bcd0fd2b99db601e4b8f4a442108ae Author: Waffle Maybe Date: Tue Oct 3 23:19:25 2023 +0400 Mark myself as vacation or whatever commit 7815641be0751ea3e2ac034585207632035af2ee Author: Michael Goulet Date: Tue Oct 3 19:06:17 2023 +0000 Gate against auto traits pre-expansion commit 36aab8df0ab8a76f1c4f95ce8becefdd8a6fe526 Merge: 268d6250299 053c4f94a09 Author: bors Date: Tue Oct 3 18:36:21 2023 +0000 Auto merge of #115301 - Zalathar:regions-vec, r=davidtwco coverage: Allow each coverage statement to have multiple code regions The original implementation of coverage instrumentation was built around the assumption that a coverage counter/expression would be associated with *up to one* code region. When it was discovered that *multiple* regions would sometimes need to share a counter, a workaround was found: for the remaining regions, the instrumentor would create a fresh expression that adds zero to the existing counter/expression. That got the job done, but resulted in some awkward code, and produces unnecessarily complicated coverage maps in the final binary. --- This PR removes that tension by changing `StatementKind::Coverage`'s code region field from `Option` to `Vec`. The changes on the codegen side are fairly straightforward. As long as each `CoverageKind::Counter` only injects one `llvm.instrprof.increment`, the rest of coverage codegen is happy to handle multiple regions mapped to the same counter/expression, with only minor option-to-vec adjustments. On the instrumentor/mir-transform side, we can get rid of the code that creates extra (x + 0) expressions. Instead we gather all of the code regions associated with a single BCB, and inject them all into one coverage statement. --- There are several patches here but they can be divided in to three phases: - Preparatory work - Actually switching over to multiple regions per coverage statement - Cleaning up So viewing the patches individually may be easier. commit f55c87966923fb8d3ba86da875225aaf687a187a Author: Joseph Ryan Date: Mon Oct 2 16:50:23 2023 -0700 bootstrap: make copying linker binaries conditional commit 4f73d3fc72abc570604a522c480d383aea766eee Merge: 43d10428c8f 3e21c1fc568 Author: bors Date: Tue Oct 3 18:02:24 2023 +0000 Auto merge of #3102 - eduardosm:typos, r=RalfJung Fix typos `*ucom` → `ucom*` commit 3e21c1fc5681b118fb27bf0c8131d73bcfa8185c Author: Ralf Jung Date: Tue Oct 3 20:00:48 2023 +0200 wording tweaks commit 268d6250299b4f08f8e669a2889fdf71388d1f39 Merge: e3c631b3de0 91433708682 Author: bors Date: Tue Oct 3 16:15:36 2023 +0000 Auto merge of #116384 - matthiaskrgr:rollup-se332zs, r=matthiaskrgr Rollup of 5 pull requests Successful merges: - #114654 (Suggest `pin!()` instead of `Pin::new()` when appropriate) - #116261 (a small wf and clause cleanup) - #116282 (Fix broken links) - #116328 (Factor out common token generation in `fluent_messages`.) - #116379 (non_lifetime_binders: fix ICE in lint opaque-hidden-inferred-bound) r? `@ghost` `@rustbot` modify labels: rollup commit 91ef03bf2f545f10db008d0ad54c3d197f539895 Author: Eduardo Sánchez Muñoz Date: Tue Oct 3 18:14:01 2023 +0200 Fix typos `*ucom` → `ucom*` commit b437069f59798c998309ff2b91eb381539722d8b Merge: 29958f07643 c7152679efd Author: bors Date: Tue Oct 3 15:49:28 2023 +0000 Auto merge of #11603 - koka831:fix/11599, r=y21 Fix: avoid changing drop order Fixes https://github.com/rust-lang/rust-clippy/issues/11599 changelog: [`redundant_locals`] No longer lints which implements Drop trait to avoid reordering commit ace85f0ae31052e5928a19797762077444f9e93c Author: León Orell Valerian Liehr Date: Tue Oct 3 17:41:25 2023 +0200 rustdoc: add support for cross-crate higher-ranked types commit 92c9bcdff463e59ee5ff9355dd4511b0f3427e6b Author: Elichai Turkel Date: Tue Oct 3 18:32:25 2023 +0300 Add missing inline attributes to Duration trait impls commit 67de1509f394414c2987af32a952a6fe66ad815a Author: León Orell Valerian Liehr Date: Tue Oct 3 17:16:51 2023 +0200 rustdoc: fix & clean up handling of cross-crate higher-ranked lifetimes commit c7152679efd5cd7c433f77eae2109170e4cc34e8 Author: koka Date: Wed Oct 4 00:13:53 2023 +0900 Apply review suggestions from @y21 commit 914337086820bcee4d755ec14d33f1c33abf5278 Merge: 5dd9313d2e3 3f0a327fbbb Author: Matthias Krüger Date: Tue Oct 3 16:24:17 2023 +0200 Rollup merge of #116379 - fmease:opaq-hid-inf-bnds-non-lt-bndrs, r=compiler-errors non_lifetime_binders: fix ICE in lint opaque-hidden-inferred-bound Opaque types like `impl for Trait` would previously lead to an ICE. r? `@compiler-errors` commit 5dd9313d2e392e180a493631e8de257e4667e31d Merge: a4ba529474a 57397de2c91 Author: Matthias Krüger Date: Tue Oct 3 16:24:17 2023 +0200 Rollup merge of #116328 - nnethercote:rustc_fluent_macro, r=davidtwco Factor out common token generation in `fluent_messages`. The failure and success cases are similar enough that they can share code. r? `@davidtwco` commit a4ba529474ae7a6f2649ca57e06d25a5a496301e Merge: 8efbc2cbae8 6ef3fd71386 Author: Matthias Krüger Date: Tue Oct 3 16:24:16 2023 +0200 Rollup merge of #116282 - rustaceanclub:master, r=davidtwco Fix broken links The previous address is no longer available, replace it with the latest available one. commit 8efbc2cbae8cdf34023c89633200c71759562aa4 Merge: 535cd8d511b aac29a0fc3b Author: Matthias Krüger Date: Tue Oct 3 16:24:15 2023 +0200 Rollup merge of #116261 - lcnr:wf-only-clause, r=davidtwco a small wf and clause cleanup - remove `Clause::from_projection_clause`, instead use `ToPredicate` - change `predicate_obligations` to directly take a `Clause` - remove some unnecessary `&` - use clause in `min_specialization` checks where easily applicable commit 535cd8d511b4840b6e6a599ebbdc8ad3b5363618 Merge: e3c631b3de0 6b58fbfd7ec Author: Matthias Krüger Date: Tue Oct 3 16:24:15 2023 +0200 Rollup merge of #114654 - estebank:suggest-pin-macro, r=davidtwco Suggest `pin!()` instead of `Pin::new()` when appropriate When encountering a type that needs to be pinned but that is `!Unpin`, suggest using the `pin!()` macro. Fix #57994. commit c0a42cc7bdc7407427952a8fee01acec101e2544 Author: Mark Rousskov Date: Tue Oct 3 09:28:03 2023 -0400 Drop the wasm32 builder This builder tested the wasm32-unknown-emscripten target, which is tier 2 (and so not eligible for testing). In the recent beta promotion, we ran into a problem with this target: emscripten doesn't support passing environment variables into the std environment, so we can't enable RUSTC_BOOTSTRAP for libtest in order to pass -Zunstable-options. We worked around this for the beta/stable branches, but given this problem, and its tier 2 status, just dropping the target's tests entirely seems warranted. Downgrading to tier 3 may also be a good idea, but that is a separate conversation not proposed here. commit 29958f076439de7d6d4839d5d90ecae9b46bda80 Merge: 81400e2db82 e465264d47f Author: bors Date: Tue Oct 3 13:07:13 2023 +0000 Auto merge of #11602 - koka831:fix/11601, r=xFrednet Avoid invoking `ignored_unit_patterns` in macro definition Fixes https://github.com/rust-lang/rust-clippy/issues/11601 The reported problem occured in [a derive macro](https://github.com/mpalmer/ct-structs/actions/runs/6386980382/job/17334587328#step:6:239). This PR avoid linting in macros. changelog: [`ignored_unit_patterns`] No longer lints inside macro definitions commit 1a56f90ee5ff65020e9992dd6e434e9ec0e46435 Author: koka Date: Tue Oct 3 21:22:54 2023 +0900 Fix: avoid changing drop order commit 3f0a327fbbb28c90fb33425aa8871d0c0d4a9c48 Author: León Orell Valerian Liehr Date: Tue Oct 3 13:50:07 2023 +0200 non_lifetime_binders: fix ICE in lint opaque-hidden-inferred-bound commit e3c631b3de09e1bd6db98d26d91d31d932d7cf60 Merge: eb0f3ed59c6 7ba649806f0 Author: bors Date: Tue Oct 3 11:49:06 2023 +0000 Auto merge of #116376 - matthiaskrgr:rollup-b3d14gq, r=matthiaskrgr Rollup of 5 pull requests Successful merges: - #115863 (Add check_unused_messages in tidy) - #116210 (Ensure that `~const` trait bounds on associated functions are in const traits or impls) - #116358 (Rename both of the `Match` relations) - #116371 (Remove unused features from `rustc_llvm`.) - #116374 (Print normalized ty) r? `@ghost` `@rustbot` modify labels: rollup commit e465264d47fbe0a19c620e320c1b5dbeae446f1e Author: koka Date: Tue Oct 3 20:36:35 2023 +0900 Avoid invoking `ignored_unit_patterns` in macro definition commit 7ba649806f0e1dd4692f7cc6f77f3f71fdeb7f8e Merge: 8e148a17e17 42c39b343d5 Author: Matthias Krüger Date: Tue Oct 3 12:24:13 2023 +0200 Rollup merge of #116374 - ouz-a:correct_message, r=RalfJung Print normalized ty Inside `mir_assign_valid_types` we are comparing normalized type of `mir_place` but in debug message we are not printing the normalized value, this changes that. commit 8e148a17e17e4fd9d98b77994c63c93d2e790614 Merge: 12e4c780ee6 c3127d161a4 Author: Matthias Krüger Date: Tue Oct 3 12:24:12 2023 +0200 Rollup merge of #116371 - nnethercote:rustc_llvm, r=bjorn3 Remove unused features from `rustc_llvm`. r? `@bjorn3` commit 12e4c780ee68c7d93a1d78bd5b16fb5eb2e64ff0 Merge: fa1cbac1ea8 2ffaeb51108 Author: Matthias Krüger Date: Tue Oct 3 12:24:12 2023 +0200 Rollup merge of #116358 - compiler-errors:match, r=lcnr Rename both of the `Match` relations Both of these names kinda were ambiguous. r? lcnr commit fa1cbac1ea8a5761c8c1a10536b227e6d3987356 Merge: 144862ede85 884af362f2d Author: Matthias Krüger Date: Tue Oct 3 12:24:11 2023 +0200 Rollup merge of #116210 - Raekye:master, r=fee1-dead Ensure that `~const` trait bounds on associated functions are in const traits or impls Zulip discussion: https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/How.20to.2Fshould.20I.20try.20to.20pinpoint.20ICEs.20related.20to.20effects.3F commit 144862ede85d0378e527f74269f0174e6e00efae Merge: 9998f4add08 42a033affa2 Author: Matthias Krüger Date: Tue Oct 3 12:24:11 2023 +0200 Rollup merge of #115863 - chenyukang:yukang-add-message-tidy-check, r=davidtwco Add check_unused_messages in tidy From https://github.com/rust-lang/rust/pull/115728#issuecomment-1715490553 The check is not 100% accurate, I guess it's enough for now. commit 673f44735357f9946943cdff0015053979e73370 Merge: f04620a5083 27f88ee273e Author: bors Date: Tue Oct 3 10:02:52 2023 +0000 Auto merge of #115025 - ouz-a:ouz_testing, r=lcnr Make subtyping explicit in MIR This adds new mir-opt that pushes new `ProjectionElem` called `ProjectionElem::Subtype(T)` to `Rvalue` of a subtyped assignment so we can unsoundness issues like https://github.com/rust-lang/rust/issues/107205 Addresses https://github.com/rust-lang/rust/issues/112651 r? `@lcnr` commit f107a50b2331e9adac586784b780e38ecb4bf8bd Merge: 3169423ce9e ea4b38820ba Author: bors Date: Tue Oct 3 10:02:52 2023 +0000 Auto merge of #115025 - ouz-a:ouz_testing, r=lcnr Make subtyping explicit in MIR This adds new mir-opt that pushes new `ProjectionElem` called `ProjectionElem::Subtype(T)` to `Rvalue` of a subtyped assignment so we can unsoundness issues like https://github.com/rust-lang/rust/issues/107205 Addresses https://github.com/rust-lang/rust/issues/112651 r? `@lcnr` commit eb0f3ed59c6508a37c6598bc9762987f053993a7 Merge: 9998f4add08 5d753abb300 Author: bors Date: Tue Oct 3 10:02:52 2023 +0000 Auto merge of #115025 - ouz-a:ouz_testing, r=lcnr Make subtyping explicit in MIR This adds new mir-opt that pushes new `ProjectionElem` called `ProjectionElem::Subtype(T)` to `Rvalue` of a subtyped assignment so we can unsoundness issues like https://github.com/rust-lang/rust/issues/107205 Addresses https://github.com/rust-lang/rust/issues/112651 r? `@lcnr` commit 42c39b343d5e5b3a65c123fc49a9b982eed86af3 Author: ouz-a Date: Tue Oct 3 10:58:46 2023 +0300 print normalized ty commit a2051dd578f70e4976e1aa3d282df399fcbcb144 Author: Nicholas Nethercote Date: Tue Oct 3 12:20:15 2023 +1100 Optimize some `alloc_from_iter` call sites. There's no need to collect an iterator into a `Vec`, or to call `into_iter` at the call sites. commit 816383c60dda68cf225164bae07f6b597261b4ab Author: Nicholas Nethercote Date: Tue Oct 3 11:54:46 2023 +1100 Remove the `TypedArena::alloc_from_iter` specialization. It was added in #78569. It's complicated and doesn't actually help performance. Also, add a comment explaining why the two `alloc_from_iter` functions are so different. commit 9998f4add08c3d09c82e00975cf3a293b30160ec Merge: 4f75af9e19d c3daf771328 Author: bors Date: Tue Oct 3 07:10:07 2023 +0000 Auto merge of #116372 - matthiaskrgr:rollup-ee9oxxa, r=matthiaskrgr Rollup of 6 pull requests Successful merges: - #113053 (add notes about non-compliant FP behavior on 32bit x86 targets) - #115726 (For a single impl candidate, try to unify it with error trait ref) - #116158 (Don't suggest nonsense suggestions for unconstrained type vars in `note_source_of_type_mismatch_constraint`) - #116351 (Add `must_use` on pointer equality functions) - #116355 (Clarify float rounding direction for signed zero) - #116361 (Bump stdarch submodule) r? `@ghost` `@rustbot` modify labels: rollup commit c3daf77132884c052fe6a09256b164b26d845405 Merge: 043fcc487a2 f2918b4a3d4 Author: Matthias Krüger Date: Tue Oct 3 08:58:50 2023 +0200 Rollup merge of #116361 - eduardosm:bump-stdarch, r=Amanieu Bump stdarch submodule r? `@Amanieu` commit 043fcc487a2fe3c286cbccd87ac29277ba5a4ae1 Merge: cebe393a4a1 07e96314ec1 Author: Matthias Krüger Date: Tue Oct 3 08:58:50 2023 +0200 Rollup merge of #116355 - orlp:signed-zero-rounding-mode, r=thomcc Clarify float rounding direction for signed zero Closes https://github.com/rust-lang/rust/issues/116339. commit cebe393a4a19738a927ad84afffbb4015d7e6f06 Merge: 634e5c9ba2d 34ea5407208 Author: Matthias Krüger Date: Tue Oct 3 08:58:49 2023 +0200 Rollup merge of #116351 - asquared31415:ptr_eq_must_use, r=workingjubilee Add `must_use` on pointer equality functions `ptr == ptr` (like all use of `==`) has a similar warning, and these functions are simple convenience wrappers over that. commit 634e5c9ba2ddc155ae95b91d21f511a8a22e9206 Merge: ff3b15e2bf1 ac5aa8c1a43 Author: Matthias Krüger Date: Tue Oct 3 08:58:48 2023 +0200 Rollup merge of #116158 - compiler-errors:unconstrained-type-var-sugg, r=wesleywiser Don't suggest nonsense suggestions for unconstrained type vars in `note_source_of_type_mismatch_constraint` The way we do type inference for suggestions in `note_source_of_type_mismatch_constraint` is a bit strange. We compute the "ideal" method signature, which takes the receiver that we *want* and uses it to compute the types of the arguments that would have given us that receiver via type inference, and use *that* to suggest how to change an argument to make sure our receiver type is inferred correctly. The problem is that sometimes we have totally unconstrained arguments (well, they're constrained by things outside of the type checker per se, like associated types), and therefore type suggestions are happy to coerce anything to that unconstrained argument. This leads to bogus suggestions, like #116155. This is partly due to above, and partly due to the fact that `emit_type_mismatch_suggestions` doesn't double check that its suggestions are actually compatible with the program other than trying to satisfy the type mismatch. This adds a hack to make sure that at least the types are fully constrained, but I guess I could also rip out this logic altogether. There would be some sad diagnostics regressions though, such as `tests/ui/type/type-check/point-at-inference-4.rs`. Fixes #116155 commit ff3b15e2bf19d39b2c8463afda183c387d993569 Merge: 9eb87c39a01 07851679cd8 Author: Matthias Krüger Date: Tue Oct 3 08:58:48 2023 +0200 Rollup merge of #115726 - compiler-errors:better-error-ref, r=estebank For a single impl candidate, try to unify it with error trait ref This allows us to point out an exact type mismatch when there's only one applicable impl. cc `@asquared31415` r? `@estebank` commit 9eb87c39a01b0a565a2649d169feaecf4de31a1a Merge: 4f75af9e19d df911dfdd62 Author: Matthias Krüger Date: Tue Oct 3 08:58:47 2023 +0200 Rollup merge of #113053 - RalfJung:x86_32-float, r=workingjubilee add notes about non-compliant FP behavior on 32bit x86 targets Based on ton of prior discussion (see all the issues linked from https://github.com/rust-lang/unsafe-code-guidelines/issues/237), the consensus seems to be that these targets are simply cursed and we cannot implement the desired semantics for them. I hope I properly understood what exactly the extent of the curse is here, let's make sure people with more in-depth FP knowledge take a close look! In particular for the tier 3 targets I have no clue which target is affected by which particular variant of the x86_32 FP curse. I assumed that `i686` meant SSE is used so the "floating point return value" is the only problem, while everything lower (`i586`, `i386`) meant x87 is used. I opened https://github.com/rust-lang/rust/issues/114479 to concisely describe and track the issue. Cc `@workingjubilee` `@thomcc` `@chorman0773` `@rust-lang/opsem` Fixes https://github.com/rust-lang/rust/issues/73288 Fixes https://github.com/rust-lang/rust/issues/72327 commit df911dfdd620cb0660e8c08857dc9b5e402946b6 Author: Ralf Jung Date: Mon Jun 26 13:03:35 2023 +0200 add notes about non-compliant FP behavior on 32bit x86 targets commit c3127d161a4db9d0f323083d896dbbf5be01be9e Author: Nicholas Nethercote Date: Tue Oct 3 15:54:44 2023 +1100 Remove unused features from `rustc_llvm`. commit 4f75af9e19d065905280ca517fd7560c73747369 Merge: 2e5a9dd6c9e 9501ff00b9b Author: bors Date: Tue Oct 3 04:37:43 2023 +0000 Auto merge of #116083 - cuviper:relnotes-1.73.0, r=Mark-Simulacrum Add release notes for 1.73.0 r? `@Mark-Simulacrum` cc `@rust-lang/release` commit 9501ff00b9b2786ba43d11a104fe6f52f4d60ed2 Author: Mark Rousskov Date: Mon Oct 2 22:49:16 2023 -0400 Fix a few typos Co-authored-by: Josh Triplett commit 2934fe07b7fd60760e0e9e7d509601b893d7b3fd Author: Michael Goulet Date: Mon Oct 2 21:31:46 2023 +0000 Point to full async fn for future commit 2c525fd758961af9f7b24dc433ec9021b4bff4dc Author: Michael Goulet Date: Mon Oct 2 21:31:46 2023 +0000 Point to full async fn for future commit 053c4f94a098be5fbb80ca881b01cc8e9c64a8a5 Author: Zalathar Date: Wed Sep 6 17:53:04 2023 +1000 coverage: Remove `next_id` methods from counter/expression IDs When these methods were originally written, I wasn't aware that `newtype_index!` already supports addition with ordinary numbers, without needing to unwrap and re-wrap. commit b1cf0c8f1b7ef70836a7842a3287bd7408d20071 Author: Zalathar Date: Sun Aug 27 20:21:35 2023 +1000 coverage: Remove code for making expression copies of BCB counters Now that coverage statements can have multiple code regions attached to them, this code is never used. commit 86a66c817124170c04035562e9f29cda3138f6ec Author: Zalathar Date: Tue Sep 19 14:15:33 2023 +1000 coverage: Store each BCB's code regions in one coverage statement If a BCB has more than one code region, those extra regions can now all be stored in the same coverage statement, instead of being stored in additional statements. commit ee9d00f6b8fd184f78161cce3a691bf55b88136d Author: Zalathar Date: Sun Aug 27 17:11:13 2023 +1000 coverage: Let each coverage statement hold a vector of code regions This makes it possible for a `StatementKind::Coverage` to hold more than one code region, but that capability is not yet used. commit 1355e1fc74102802aea01c744acafec0c4fabee5 Author: Zalathar Date: Sun Sep 17 22:22:21 2023 +1000 coverage: Update comments/logs that referred to `CoverageSpan` The concrete type `CoverageSpan` is no longer used outside of the `spans` module. This is a separate patch to avoid noise in the preceding patch that actually encapsulates coverage spans. commit e29db47176242ed869cdb4866eb8cad81d2fd37b Author: Zalathar Date: Sun Sep 17 22:22:21 2023 +1000 coverage: Encapsulate coverage spans By encapsulating the coverage spans in a struct, we can change the internal representation without disturbing existing call sites. This will be useful for grouping coverage spans by BCB. This patch includes some changes that were originally in #115912, which avoid the need for a particular test to deal with coverage spans at all. (Comments/logs referring to `CoverageSpan` are updated in a subsequent patch.) commit 59a11af1f9f91ca5ca4c632c9f7d097ea5fb655c Author: Zalathar Date: Thu Sep 7 19:58:11 2023 +1000 coverage: Mappings for unused functions can all be zero There is no need to include a dummy counter reference in the coverage mappings for an unused function. commit 93677276bc495e78f74536385a16201d465fd523 Author: Peter Jaszkowiak Date: Sat Aug 12 13:00:05 2023 -0600 Invoke `backtrace-rs` buildscript in `std` buildscript Based on #99883 by @Arc-blroth Depends on rust-lang/backtrace-rs#556 and rust-lang/cc-rs#705 commit 81400e2db821317741ca811e5eb71bce6bcd49f7 Merge: 08c429f241b d5cc97e32c9 Author: bors Date: Tue Oct 3 01:26:29 2023 +0000 Auto merge of #11589 - koka831:fix/10198, r=giraffate std_instead_of_core: avoid lint inside of proc-macro - fixes https://github.com/rust-lang/rust-clippy/issues/10198 note: The lint for the reported `thiserror::Error` has been suppressed by [Don't lint unstable moves in std_instead_of_core](https://github.com/rust-lang/rust-clippy/pull/9545/files#diff-2cb8a24429cf9d9898de901450d640115503a10454d692dddc6a073a299fbb7eR29) because `thiserror::Error` internally implements `std::error::Error for (derived struct)`. changelog: [`std_intead_of_core`]: avoid linting inside proc-macro I confirmed this change fixes the problem:
test result without the change ```console error: used import from `std` instead of `core` --> tests/ui/std_instead_of_core.rs:65:14 | LL | #[derive(ImplStructWithStdDisplay)] | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the derive macro `ImplStructWithStdDisplay` (in Nightly builds, run with -Z macro-backtrace for more info) ```
commit c373d206cd9ed7beec89c72e61d76ad61d6d35c1 Author: Michael Goulet Date: Tue Oct 3 00:51:13 2023 +0000 Address review nits commit 90dfa24415d4f29e1970bf215458ccefec60f85f Author: Michael Goulet Date: Sat Sep 30 19:28:40 2023 +0000 Only reachable traits commit afea0b4eab6f5e91edf70102194d77c8f8f20479 Author: Travis Cross Date: Fri Sep 29 20:56:49 2023 +0000 Fill in prose to describe the `async_fn_in_trait` lint We're stabilizing `async fn` in trait (AFIT), but we have some reservations about how people might use this in the definitions of publicly-visible traits, so we're going to lint about that. This is a bit of an odd lint for `rustc`. We normally don't lint just to have people confirm that they understand how Rust works. But in this one exceptional case, this seems like the right thing to do as compared to the other plausible alternatives. In this commit, we describe the nature of this odd lint. commit 28d58f6524a10406c60c170c5e9eae70c8a7b76d Author: Michael Goulet Date: Tue Sep 26 20:20:25 2023 +0000 Bless tests commit ec79720c1e908728924c9634aac36fdc1fecd425 Author: Michael Goulet Date: Tue Sep 26 20:20:21 2023 +0000 Add async_fn_in_trait lint commit f8fc0d771623875e6f9515c22aa58b4aedba839e Author: Scott McMurray Date: Mon Oct 2 17:32:01 2023 -0700 Use `addr_eq` in `{Arc,Rc}::ptr_eq` Since it's made for stuff like this (see 106447) commit 0c6d279728b6afc9309638e22a0048a3756a7e87 Author: James Haywood Date: Mon Oct 2 19:22:42 2023 -0400 Appease tidy commit 07851679cd8ced5933095c4173d3877c1abc96dd Author: Michael Goulet Date: Sun Sep 10 03:33:07 2023 +0000 Point out the actual mismatch error commit 8be12f4ed70c55652fefdec63d094974d00e164c Author: Michael Goulet Date: Sun Sep 10 03:21:52 2023 +0000 For a single impl candidate, try to unify it with error trait ref commit f96cfb533a5cb84277dd894854fbac44628626cf Author: James Haywood Date: Sun Oct 1 23:35:22 2023 -0400 Adapt `todo!` documentation to mention displaying custom values Correct hidden trait in doc test commit 2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b Merge: 5333b878c8b 5bcf4f26ac4 Author: bors Date: Mon Oct 2 22:02:12 2023 +0000 Auto merge of #102099 - InnovativeInventor:re-cold-land, r=nikic Rebased: Mark drop calls in landing pads cold instead of noinline I noticed that certain inlining optimizations were missing while staring at some compiled code output. I'd like to see this relanded, so I rebased the PR from `@erikdesjardins` (PR #94823). This PR reapplies https://github.com/rust-lang/rust/pull/92419, which was reverted in https://github.com/rust-lang/rust/pull/94402 due to https://github.com/rust-lang/rust/issues/94390. Fixes https://github.com/rust-lang/rust/issues/46515, fixes https://github.com/rust-lang/rust/issues/87055. Update: fixes #97217. commit f2918b4a3d4a36e0cca5dde4247817ef48af4c1f Author: Eduardo Sánchez Muñoz Date: Mon Oct 2 23:43:35 2023 +0200 Bump stdarch submodule commit 0eb8973fa9637925b9d46843971ad03a3ccb0e82 Author: Josh Stone Date: Mon Oct 2 14:41:10 2023 -0700 Shuffle around some 1.73.0 relnotes commit c6bb73101e3de8b5f15d9763a468f0e93770d7f2 Author: Josh Stone Date: Mon Oct 2 14:37:34 2023 -0700 Apply suggestions for 1.73.0 relnotes Co-authored-by: Mark Rousskov Co-authored-by: Urgau <3616612+Urgau@users.noreply.github.com> commit ac5aa8c1a4370b34674d18ef20b642645d2172e0 Author: Michael Goulet Date: Mon Sep 25 18:57:12 2023 +0000 Don't suggest nonsense suggestions for unconstrained type vars in note_source_of_type_mismatch_constraint commit 2ffaeb5110818c7f0c768c715afecb5bc20b5a18 Author: Michael Goulet Date: Mon Oct 2 21:06:09 2023 +0000 Rename both of the Match relations commit 27f88ee273edfbe69a7787a523d6ba081ab02709 Author: ouz-a Date: Mon Oct 2 11:22:48 2023 +0300 have better explanation for `relate_types` commit 5d753abb300eebfb6492dc2b47bd32052a322b71 Author: ouz-a Date: Mon Oct 2 11:22:48 2023 +0300 have better explanation for `relate_types` commit 646d8d982264b91bd1b434b30b25845f21508c48 Author: ouz-a Date: Sat Sep 30 13:44:31 2023 +0300 change is_subtype to relate_types commit 6f0c5ee2d4c9ced0fa9d0e698b6a136cfdc51949 Author: ouz-a Date: Sat Sep 30 13:44:31 2023 +0300 change is_subtype to relate_types commit 8c3406f8bc3c20cb38c44514f1017c25ee566cd5 Author: ouz-a Date: Mon Aug 28 11:19:19 2023 +0300 Add docs, remove code, change subtyper code commit cd7f47193182d1d557a83593bcff6afe0568fc53 Author: ouz-a Date: Mon Aug 28 11:19:19 2023 +0300 Add docs, remove code, change subtyper code commit ea4b38820bafe9d7016cf19d35e977b08f0cbdd3 Author: ouz-a Date: Wed Aug 16 08:43:30 2023 +0300 subtyping_projections commit 4e9e0aae33261263e0dc8d5411097efef94f07e7 Author: ouz-a Date: Wed Aug 16 08:43:30 2023 +0300 subtyping_projections commit 3148e6a9933b17b28ed6c7b8d8bd6c8e49fe4a50 Author: ouz-a Date: Wed Aug 16 08:43:30 2023 +0300 subtyping_projections commit 5333b878c8bc1c4267a67ea3682663629e47541a Merge: 8e47113d71e 132e38366fd Author: bors Date: Mon Oct 2 20:11:28 2023 +0000 Auto merge of #116356 - tmandry:rollup-trfidc8, r=tmandry Rollup of 5 pull requests Successful merges: - #114453 (Print GHA log groups to stdout instead of stderr) - #114454 (Replace `HashMap` with `IndexMap` in pattern binding resolve ) - #116289 (Add missing #[inline] on AsFd impl for sys::unix::fs::File) - #116349 (ensure the parent path's existence on `x install`) - #116350 (Improve wording of `hint::black_box` docs) r? `@ghost` `@rustbot` modify labels: rollup commit 132e38366fd2a1404d74d0757e51c81a2f56cb4d Merge: d7621cdb19e 44c9818993d Author: Tyler Mandry Date: Mon Oct 2 16:09:43 2023 -0400 Rollup merge of #116350 - Nilstrieb:in-situ, r=Dylan-DPC Improve wording of `hint::black_box` docs The wording is a bit confusing. squash of #109634 commit d7621cdb19efe246b62f2d25ed9bfe3afe6f2917 Merge: 1edf7233fae 2c8759ef8a9 Author: Tyler Mandry Date: Mon Oct 2 16:09:43 2023 -0400 Rollup merge of #116349 - onur-ozkan:hfix, r=tmandry ensure the parent path's existence on `x install` fixes https://github.com/rust-lang/rust/pull/116127#issuecomment-1743454109 cc `@tmandry` commit 1edf7233faefe64265898db10f5df4b57e9beb5d Merge: af77806bee4 133aa56a84a Author: Tyler Mandry Date: Mon Oct 2 16:09:42 2023 -0400 Rollup merge of #116289 - linkmauve:patch-1, r=the8472 Add missing #[inline] on AsFd impl for sys::unix::fs::File This operation should be extremely cheap, at most the `mov` of the underlying file descriptor, but due to this missing `#[inline]` it is currently a function call. commit af77806bee45ca8a73b24746b84b011840cddc39 Merge: 14f62490185 6ca07235a60 Author: Tyler Mandry Date: Mon Oct 2 16:09:42 2023 -0400 Rollup merge of #114454 - Nilstrieb:no-evil-sorting, r=cjgillot Replace `HashMap` with `IndexMap` in pattern binding resolve fixes https://github.com/rust-lang/rust/pull/114332#discussion_r1284189179 commit 14f624901853c1ce36c91262448d08ffbff6c1ce Merge: 8e47113d71e 88b99851a2b Author: Tyler Mandry Date: Mon Oct 2 16:09:41 2023 -0400 Rollup merge of #114453 - Kobzol:ci-group-stdout, r=onur-ozkan Print GHA log groups to stdout instead of stderr In all other places (e.g. `bootstrap.py`, `opt-dist`), we use stdout instead of stderr. I think that using stderr might be causing some discrepancies in the log, where sometimes the contents of a group "leak" outside the group. Let's see what happens if we use stdout instead. It's possible that it will be worse, since we print most stuff to stderr (?). r? `@ghost` commit 07e96314ec1ea2cd28f10224a90f1647e3082515 Author: Orson Peters Date: Mon Oct 2 22:05:17 2023 +0200 Clarify float rounding direction for signed zero commit 76b70eb0337836cf3197fb29e85195f9375e48be Author: Jakub Beránek Date: Mon Oct 2 21:38:50 2023 +0200 Add new bors try branches to CI commit 2d73d30a3c4d5d06dbdc35c3cf2aabf9e3387a3d Author: Lukas Wirth Date: Fri Sep 29 18:15:07 2023 +0200 Fix incorrect inlining of RangeInclusive::size_hint commit b25c84510d8ba2a90f49d265a57395ce05ad6a64 Author: Lukas Wirth Date: Fri Sep 29 18:02:59 2023 +0200 Add some docs regarding rustc_abi rust-analyzer compat changes commit 6d141c11c0acd3c943e110d6d1778f62321720fe Author: Lukas Wirth Date: Fri Sep 29 18:00:06 2023 +0200 Implement Deref for Layout commit 67e5eb6cec42b7b13e93bdb57e2d9f3a0b710d6f Author: Lukas Wirth Date: Fri Sep 29 17:52:05 2023 +0200 Cfg out ReprOption::field_shuffle_seed commit e8a2673159f69be298287328a24e17e3ed1da5f0 Author: Lukas Wirth Date: Fri Sep 29 17:19:41 2023 +0200 Add VariantIdx back commit f14b7c9443cb045bd04a1f07c1731ba514111048 Author: Lukas Wirth Date: Fri Sep 29 17:14:56 2023 +0200 Move FieldIdx and Layout to rustc_target commit b47ad3b744e90ad4b774ab665b42cd281e70f5dc Author: Lukas Wirth Date: Fri Sep 29 17:09:56 2023 +0200 Bring back generic FieldIdx commit 3b99d73f5a3d47a8bb41af09129e84a6dc6631d6 Author: Lukas Wirth Date: Fri Sep 29 16:19:43 2023 +0200 Unglob rustc_abi imports commit 08c429f241b985c277e63a6e95c0a60d49f946f1 Merge: 331d01e2bf5 07e63291ecc Author: bors Date: Mon Oct 2 18:40:32 2023 +0000 Auto merge of #11596 - blyxyas:fix-fp-needless_pass_by_ref_mut, r=Jarcho Move `needless_pass_by_ref_mut`: `suspicious` -> `nursery` [Related to [this Zulip thread](https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/needless_pass_by_ref_mut.20isn't.20ready.20for.20stable)] `needless_pass_by_ref_mut` has been released with some important bugs (notably having a lot of reported false positives and an ICE). So it may not be really ready for being in stable until these problems are solved. This PR changes the lint's category from `suspicious` to `nursery`, just that. changelog: none commit 07e63291eccb2aad2e42c31e11f614ee9f7592d8 Author: blyxyas Date: Mon Oct 2 20:14:43 2023 +0200 Modify tests to account for the new allow-by-default `needless_pass_by_ref_mut` commit 44c9818993d1ec5e7e6debdbb33ed2139341b60f Author: 4gboframram <79847791+4gboframram@users.noreply.github.com> Date: Sun Mar 26 12:48:01 2023 -0400 Improve wording of `hint::black_box` docs The wording is a bit confusing. Co-authored-by: Chris Denton commit 2c8759ef8a91b70b567a7459694635ed70c19248 Author: onur-ozkan Date: Mon Oct 2 20:48:53 2023 +0300 ensure the parent path's existence on `x install` Signed-off-by: onur-ozkan commit 8e47113d71ed3922084571d70deba661f0a20001 Merge: 5ead7452e55 dcfa64bc2d2 Author: bors Date: Mon Oct 2 17:48:05 2023 +0000 Auto merge of #116331 - lqd:jemalloc-update, r=nnethercote update jemalloc-sys to most recent release I wouldn't expect this to show perf improvements: IIUC this release should only contain a bugfix. cc `@nnethercote` r? `@ghost` commit 6ca07235a600bfc20b5fda2d5d6e985ca81d124f Author: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri Aug 4 11:30:09 2023 +0200 Replace `HashMap` with `IndexMap` in pattern binding resolve It will be iterated over, so we should avoid using `HashMap`. commit 43d10428c8fc022cc3cdda6ba3272b53f78c8310 Merge: 6687c075dfb cfbcc0e6f56 Author: bors Date: Mon Oct 2 16:32:57 2023 +0000 Auto merge of #3099 - RalfJung:abi-target-feature, r=RalfJung add test for a function ABI mismatch due to target features Cc https://github.com/rust-lang/miri/issues/3095 commit cfbcc0e6f565a6848e519570cdb4dcd4c3c34fc5 Author: Ralf Jung Date: Mon Oct 2 18:29:49 2023 +0200 add test for a function ABI mismatch due to target features commit 5ead7452e55fc00421fbbda34f570a1673422368 Merge: b0889cb4ed0 cfe9e136275 Author: bors Date: Mon Oct 2 15:56:33 2023 +0000 Auto merge of #116346 - matthiaskrgr:rollup-uwepk8j, r=matthiaskrgr Rollup of 3 pull requests Successful merges: - #116313 (Some small cleanups in `rustc_abi`) - #116326 (Correct misleading std::fmt::Binary example (#116165)) - #116340 (`skip_binder` to `instantiate_identity`) r? `@ghost` `@rustbot` modify labels: rollup commit 209789ef4c20c7076678a67974c1f399b0fcd2c2 Author: Jakub Beránek Date: Wed Aug 9 20:56:11 2023 +0200 Add artifact size and step duration summaries from `opt-dist` to github job summary commit 34ea540720828538d858cf66cc8473bb2f54e713 Author: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon Oct 2 15:10:51 2023 +0000 add must_use on pointer equality functions commit f1ede97b145c084b14579c467c4276d247193adf Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 2 14:44:10 2023 +0000 Update portable-simd test and implement new simd_* platform intrinsics commit cfe9e136275d575e101d22ca1b185e20c8b9a936 Merge: b3853ccc9d1 dbc2cc8717d Author: Matthias Krüger Date: Mon Oct 2 16:23:54 2023 +0200 Rollup merge of #116340 - lcnr:early-binder-skip_binder, r=compiler-errors `skip_binder` to `instantiate_identity` commit b3853ccc9d1f0f444682441d1c1a73453960fb04 Merge: e51a2aaa4ec f2ecf7c5111 Author: Matthias Krüger Date: Mon Oct 2 16:23:53 2023 +0200 Rollup merge of #116326 - Colonial-Dev:issue-116165-fix, r=joshtriplett Correct misleading std::fmt::Binary example (#116165) Nothing too crazy... - Add two to the width specifier (so all 32 bits are correctly displayed) - Pad out the compared string so the assert passes - Add `// Note` comment highlighting the need for the extra width when using the `#` flag. The exact contents (and placement?) of the note are, of course, highly bikesheddable. commit e51a2aaa4ec54d970ec80c3470df5546139dae98 Merge: b0889cb4ed0 17e3793eb16 Author: Matthias Krüger Date: Mon Oct 2 16:23:53 2023 +0200 Rollup merge of #116313 - nnethercote:rustc_abi, r=the8472 Some small cleanups in `rustc_abi` Minor things I found while looking at this crate's code. r? `@the8472` commit bf4df0617fa649f90bc06ccf4b19ec5980fb2729 Author: Chinedu Francis Nwafili Date: Mon Oct 2 10:08:03 2023 -0400 Tidy commit 9536ec32bf18a60d28e9184e3c0b23d94526def0 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 2 14:01:23 2023 +0000 Temporarily ignore regex test which gets miscompiled when using an LLVM sysroot cc #1395 commit 9bb55a038f647fc3d44cbf68e7d7ab1f13474e97 Author: Chinedu Francis Nwafili Date: Mon Oct 2 09:54:45 2023 -0400 Tidy commit c974bc89b874fa5a46dfb2db8e983d4b864e42c5 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 19 21:47:17 2023 +0000 Update regex and implement necessary AArch64 vendor intrinsics Upstream has removed the shootout-regex-dna example. commit cf36f4e0dc6091da2008901a9b1955bc4526acaf Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 19 13:10:38 2023 +0000 Update rand test commit b49adfeea512dde803222a063c8f079346fbfda5 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Sep 2 17:08:34 2023 +0000 Compile cg_clif with -Zallow-features=rustc_private Fixes #1218 commit 654bc614dd81557e9a52084f23ec82a12d1fcd60 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 2 13:06:07 2023 +0000 Fix simd_shuffle_generic intrinsic commit 67379c400672adc389b3671da7e009677b1f4520 Author: Chinedu Francis Nwafili Date: Mon Oct 2 08:59:31 2023 -0400 Address misc feedback commit 5aeae0524e7978585fd8ee0f7365099b7c7bae2a Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 2 12:57:45 2023 +0000 Rustup to rustc 1.75.0-nightly (e0d7ed1f4 2023-10-01) commit aeeed8a683ed53cf2036030cdd635dcf23b94342 Merge: cb55ce11dc8 81d219a27da Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon Oct 2 12:52:42 2023 +0000 Sync from rust e0d7ed1f453fb54578cc96dfea859b0e7be15016 commit 3f0da4dda29c1dd058ab2ee0f4ddf3ff0d8a8bac Author: blyxyas Date: Mon Oct 2 13:28:45 2023 +0200 Move `needless_pass_by_ref_mut`: `suspicious` -> `nursery` commit dbc2cc8717dd8c8006595d9e9c91ad472109165a Author: lcnr Date: Mon Oct 2 13:15:29 2023 +0200 `skip_binder` to `instantiate_identity` commit b0889cb4ed0e6f3ed9f440180678872b02e7052c Merge: 781ebbec8a0 82d23a6275f Author: bors Date: Mon Oct 2 09:41:42 2023 +0000 Auto merge of #116276 - lqd:lld-sysroot, r=onur-ozkan bootstrap: copy self-contained linking components to `stage0-sysroot` I hit this issue while trying to bootstrap using a rustc where `rust-lld` is used by default: this was the cause of the failure to profile rustc-perf's bootstrap benchmark in https://github.com/rust-lang/rust/pull/113382. `stage0-sysroot` currently only has libs and self-contained objects, not the other self-contained linking components yet. Most notably, it does not contain the linker and wrappers that we build, and that rustup distributes. If you try to bootstrap using the bootstrap compiler's `rust-lld`, it will fail to link std at stage0 because `rust-lld` and the `gcc-ld` wrappers, will not be found in `stage0-sysroot/lib/rustlib/x86_64-unknown-linux-gnu/bin`. This PR copies the `bin` directory next to the `lib` directory when `rust.lld` is enabled in the config (though maybe it could be done unconditionally, the fact that we need it to link does not necessarily mean that we'd want to build and provide it at stage1). cc `@Kobzol` who also encountered this issue while using lld during bootstrap. commit 5bcf4f26ac44284b0dbc9b53404fa5dd8a0db01a Author: Nikita Popov Date: Mon Oct 2 10:45:49 2023 +0200 Limit to LLVM 17.0.2 to work around WinEH codegen bug commit ebbc68769d1207e8036cfbff00e5b8016e9a16b7 Author: Nikita Popov Date: Tue Aug 8 11:34:07 2023 +0200 Update stack protector test We no longer generate a protector for the strong case in this test, which is actually the expected behavior per the test comment. commit 0608fca3adec23ad95e49eec2e17a4377c7c634a Author: Nikita Popov Date: Tue Aug 8 11:28:37 2023 +0200 Fix codegen tests on panic=abort targets commit 31ee8b18188c748bf73cce52478c61629ed889cc Author: Erik Desjardins Date: Thu Mar 10 17:10:36 2022 -0500 Reapply: Mark drop calls in landing pads cold instead of noinline Co-authored-by: Max Fan Co-authored-by: Nikita Popov commit 8dc92a360c3f8df35ea9d7df566159b79c8c737f Author: Ralf Jung Date: Mon Oct 2 09:49:45 2023 +0200 remove another unused Key impl commit f04620a50839bb4d99ca53acb586ee8a75d08ac9 Merge: 81d219a27da 2860a89cb1d Author: bors Date: Mon Oct 2 07:41:52 2023 +0000 Auto merge of #115898 - onur-ozkan:config-change-tracking, r=Mark-Simulacrum bootstrap major change detection implementation The use of `changelog-seen` and `bootstrap/CHANGELOG.md` has not been functional in any way for many years. We often do major/breaking changes but never update the changelog file or the `changelog-seen`. This is an alternative method for tracking major or breaking changes and informing developers when such changes occur. Example output when bootstrap detects a major change: ![image](https://github.com/rust-lang/rust/assets/39852038/ee802dfa-a02b-488b-a433-f853ce079b8a) commit 781ebbec8a0a2fdba7ea8113e09e21e972448d66 Merge: 15783292e5e 7d3dcd918eb Author: bors Date: Mon Oct 2 07:41:52 2023 +0000 Auto merge of #115898 - onur-ozkan:config-change-tracking, r=Mark-Simulacrum bootstrap major change detection implementation The use of `changelog-seen` and `bootstrap/CHANGELOG.md` has not been functional in any way for many years. We often do major/breaking changes but never update the changelog file or the `changelog-seen`. This is an alternative method for tracking major or breaking changes and informing developers when such changes occur. Example output when bootstrap detects a major change: ![image](https://github.com/rust-lang/rust/assets/39852038/ee802dfa-a02b-488b-a433-f853ce079b8a) commit dcfa64bc2d295a444ceeb88921231fbef4a1725b Author: Rémy Rakic Date: Mon Oct 2 07:41:51 2023 +0000 update jemalloc-sys to most recent release commit a648c26c2c847b92074c44643cfd820bc78c88e1 Author: Ralf Jung Date: Mon Oct 2 09:01:51 2023 +0200 remove Key impls for types that involve an AllocId commit bfc0f23acb49adbd55a04ed84fba4badc0a1be04 Author: Ralf Jung Date: Mon Oct 2 08:35:08 2023 +0200 MIRI -> Miri commit ec2e00c4045f49f8efc5b1490b6276ecb364b2dd Author: Ralf Jung Date: Mon Oct 2 08:34:10 2023 +0200 update some comments around swap() commit 57397de2c91bfdb6b57b83fe96d8721c12f55c98 Author: Nicholas Nethercote Date: Mon Oct 2 16:04:35 2023 +1100 Fix a comment. Compiling any part of the compiler will almost certainly require Nightly. commit 5f4177a786500d06733d6fba71c33e15191c8cf4 Author: Nicholas Nethercote Date: Mon Oct 2 16:37:05 2023 +1100 Factor out common token generation in `fluent_messages`. The failure and success cases are similar enough that they can share code. commit 15783292e5e26336f76ddc2123d66025ec6d84b7 Merge: 30ec74728da 18787914aa2 Author: bors Date: Mon Oct 2 04:17:01 2023 +0000 Auto merge of #116325 - scottmcm:addr_eq, r=dtolnay Add `ptr::addr_eq` Seconded ACP: https://github.com/rust-lang/libs-team/issues/274#issuecomment-1741853598 Tracking issue: https://github.com/rust-lang/rust/issues/116324 cc `@dtolnay` https://github.com/rust-lang/rust/issues/106447 commit f2ecf7c51114fe4b620334843eb4a6f6d3f6cbfd Author: James Haywood Date: Sun Oct 1 23:58:54 2023 -0400 Correct misleading std::fmt::Binary example commit 30ec74728dafd672d9b53d4037694a7dcd71a9de Merge: 79bfd93d5a9 ba0b7f0f010 Author: bors Date: Mon Oct 2 02:26:38 2023 +0000 Auto merge of #116317 - ravenclaw900:track-caller-unwrap-or-else, r=Mark-Simulacrum Add track_caller attribute to Result::unwrap_or_else Fixes issue where panics in unwrap_or_else callbacks marked with the `track_caller` attribute appear as errors in core. commit 18787914aa24bac7237e7abd96dfffed4fa73b61 Author: Scott McMurray Date: Sun Oct 1 18:56:38 2023 -0700 Add `ptr::addr_eq` commit 79bfd93d5a9cf73d312b72158c1d2289453c18c7 Merge: e0d7ed1f453 3f4a289016e Author: bors Date: Mon Oct 2 00:03:52 2023 +0000 Auto merge of #116207 - Ayush1325:uefi_stdio, r=Mark-Simulacrum Stdio support for UEFI - Uses Simple Text Output Protocol and Simple Text Input Protocol - Reading is done one character at a time - Writing is done with max 4096 characters # Quirks ## Output Newline - UEFI uses CRLF for newline. So when running the application in UEFI shell (qemu VGA), the output of `println` looks weird. - However, since the UEFI shell supports piping output, I am unsure if doing any output post-processing is a good idea. UEFI shell `cat` command seems to work fine with just LF. ## Input Newline - `Stdin.read_line()` method is broken in UEFI shell. Pressing enter seems to be read as CR, which means LF is never encountered. - Works fine with input redirection from file. CC `@dvdhrm` commit 331d01e2bf5e0c60271bad26aea9bf1db604d3e0 Merge: aee3daf90ba 258b9a85627 Author: bors Date: Sun Oct 1 22:17:18 2023 +0000 Auto merge of #11265 - Alexendoo:print-literal-unicode-escapes, r=llogiq Don't escape unicode escape braces in `print_literal` Fixes #11264 changelog: none commit 17e3793eb16def597e69542669a376b109af46b2 Author: Nicholas Nethercote Date: Sun Oct 1 21:35:07 2023 +1100 Name some local variables more consistently. By making every `alt_foo` exactly match a `foo`. commit e0d7ed1f453fb54578cc96dfea859b0e7be15016 Merge: 51ddc746797 eac7bcde5fe Author: bors Date: Sun Oct 1 22:01:44 2023 +0000 Auto merge of #116281 - Nadrieril:eager-const-eval, r=cjgillot Cleanup number handling in match exhaustiveness Doing a little bit of cleanup; handling number constants was somewhat messy. In particular, this: - evals float consts once instead of repetitively - reduces `Constructor` from 88 bytes to 56 (`mir::Const` is big!) The `fast_try_eval_bits` function was mostly constructed from inlining existing code but I don't fully understand it; I don't follow how consts work and are evaluated very well. commit 258b9a856273a0e6bbf6becd1dd769cb20228815 Author: Alex Macleod Date: Mon Jul 31 20:22:39 2023 +0000 Don't escape unicode escape braces in print_literal commit 51ddc7467978e265d2004d58980580293734ca93 Merge: 0e1dd179f19 3de082497e4 Author: bors Date: Sun Oct 1 20:14:42 2023 +0000 Auto merge of #116304 - Zalathar:unreachable, r=cjgillot coverage: Regression test for functions with unreachable bodies This is a regression test for the coverage issue that was addressed temporarily by #116166, and is tracked by #116171. --- If we instrument a function for coverage, but all of its counter-increment statements are removed by MIR optimizations, LLVM will think it isn't instrumented and it will disappear from coverage maps and coverage reports. Most MIR opts won't cause this because they tend not to remove statements from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends with `TerminatorKind::Unreachable`. Currently we have worked around this by turning off `UnreachablePropagation` when coverage instrumentation is enabled, which is why this test is able to pass. --- `@rustbot` label +A-code-coverage commit eac7bcde5fe3127e1191e9e56af834d8889555d6 Author: Nadrieril Date: Sat Sep 30 23:54:31 2023 +0200 Move `eval_bits` optimization upstream commit 3f4a289016ed2c7ae351dd77c309ca17ecc1f87a Author: Ayush Singh Date: Thu Sep 28 00:33:24 2023 +0530 Stdio for UEFI - Uses Simple Text Output Protocol and Simple Text Input Protocol - Reading is done one character at a time - Writing is done with max 4096 characters Signed-off-by: Ayush Singh commit b0a72173bbbdb2cd7b2c7411d66232f271fc6ec7 Author: Ayush Singh Date: Mon Oct 2 00:05:05 2023 +0530 Update UEFI docs - Mention stdio support - Update the example Signed-off-by: Ayush Singh commit 0e1dd179f1968d534c656e4fd0be8ccf27438d21 Merge: 16b7b39fddd 7326cd98b91 Author: bors Date: Sun Oct 1 18:27:00 2023 +0000 Auto merge of #116259 - nnethercote:entry_point_type, r=cjgillot Factor out duplicated `entry_point_type` functions A small but nice cleanup. commit 16b7b39fdddff00c237c71e237881f835b43cad6 Merge: 6c29b45439a cfb819fa7e7 Author: bors Date: Sun Oct 1 16:41:03 2023 +0000 Auto merge of #116228 - bvanjoi:fix-116164, r=cjgillot resolve: skip underscore character during candidate lookup Fixes #116164 In use statement, an underscore is merely a placeholder symbol and does not bind to any name. Therefore, it can be safely ignored. commit aee3daf90ba36fb14e3b9f04ea0eea97fd2ec6ad Merge: ec15630c5d4 6f1a78ffa85 Author: bors Date: Sun Oct 1 16:33:04 2023 +0000 Auto merge of #11593 - koka831:fix/10511, r=xFrednet Use Span#from_expansion instead of in_external_macro - fixes #10511 I checked [the reported repository](https://github.com/rust-lang/rust-clippy/issues/10511#issuecomment-1474271205) and found that clippy hangs at [py_sync.rs#L85](https://github.com/rigetti/qcs-sdk-rust/blob/842094068ed6174ba08b52a2fbae39dda77cbd00/crates/python/src/py_sync.rs#L85), where a macro(`py_function_sync_async`) defines type parameters. this macro is used in the same crate, so `in_external_macro` wouldn't catch them. This PR fixes the problem by using `Span#from_expansion`. --- changelog: ICE: [`implicit_hasher`]: No longer lints inside macros, which could cause ICEs [#11593](https://github.com/rust-lang/rust-clippy/pull/11593) commit ec15630c5d44bd2620da932db10f894ac8a0b0d7 Merge: cbe67bc2d63 0f8b8625bd3 Author: bors Date: Sun Oct 1 16:20:24 2023 +0000 Auto merge of #11592 - schubart:fix_documentation_link, r=flip1995 Fix documentation link The file pointed to by the old link https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 did not talk about categories and levels. The new link (hopefully) points here https://doc.rust-lang.org/stable/clippy/ which has a nice table explaining the mappings. changelog: none commit cbe67bc2d635f0a4a600f9e27d7df802d3510c27 Merge: 0e43a04fabc 9dfd60cf4f3 Author: bors Date: Sun Oct 1 16:06:57 2023 +0000 Auto merge of #11590 - Tyrubias:non_ex_false_positive, r=Alexendoo Don't lint `manual_non_exhaustive` when enum is `#[non_exhaustive]` Fixes #11583 changelog: Fix [`manual_non_exhaustive`] false positive for unit enum variants when enum is explicitly `non_exhaustive`. commit 0f8b8625bd309721099002813b8db9290b2bb411 Author: Michael Schubart Date: Sun Oct 1 16:32:16 2023 +0100 Fix documentation link The file pointed to by the old link https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 did not talk about categories and levels. The new link (hopefully) points here https://doc.rust-lang.org/stable/clippy/ which has a nice table explaining the mappings. commit 6f1a78ffa85b1fc67517a0522530907d0025a5f5 Author: koka Date: Mon Oct 2 00:38:01 2023 +0900 Use Span#from_expansion instead of in_external_macro commit 9dfd60cf4f33c9af8e37d4a4956f56626bac2b3c Author: Victor Song Date: Sun Oct 1 09:54:45 2023 -0500 Remove extraneous `#[non_exhaustive]` check in lint commit ba0b7f0f0105f497cd8c6ddffef0c425473fdbb8 Author: ravenclaw900 <50060110+ravenclaw900@users.noreply.github.com> Date: Sun Oct 1 09:42:37 2023 -0500 Add track_caller attribute to Result::unwrap_or_else commit 6c29b45439a9523e2f2cdf99e40cd5443db9677d Merge: 871407a0341 bb5344a1bff Author: bors Date: Sun Oct 1 14:38:51 2023 +0000 Auto merge of #116224 - nnethercote:rustc_arena-overhaul, r=cjgillot `rustc_arena` overhaul I find the `rustc_arena` a bit hard to read. These commits make it better. r? `@cjgillot` commit 7d3dcd918eb1f1308a1d901821ede3041d563ae9 Author: onur-ozkan Date: Sun Oct 1 16:55:46 2023 +0300 add triagebot notification for bootstrap config changes Signed-off-by: onur-ozkan commit 78eed2dfe129ce8ee0f7acf537030e2b5e35c3ce Author: onur-ozkan Date: Sun Oct 1 16:55:27 2023 +0300 add Changelog topic to bootstrap/README.md Signed-off-by: onur-ozkan commit 2860a89cb1d795e2bf3226012b0a11bd44fa1433 Author: onur-ozkan Date: Sun Oct 1 16:54:52 2023 +0300 implement major change tracking for the bootstrap configuration Signed-off-by: onur-ozkan commit 957de61594635d473b488eacbb2cc0093645e6a4 Author: onur-ozkan Date: Sun Oct 1 16:54:52 2023 +0300 implement major change tracking for the bootstrap configuration Signed-off-by: onur-ozkan commit 871407a0341262d2a86703ca43b449d35fa5f236 Merge: c16823d757b ca596528662 Author: bors Date: Sun Oct 1 12:49:29 2023 +0000 Auto merge of #115554 - Kobzol:single-cgu, r=Mark-Simulacrum Build `rustc` with a single CGU on x64 Linux This PR adds the `rust.codegen-units=1` setting when compiling the 64-bit Linux `rustc` artifact (the one used for try builds and Linux rustup distribution). This had mixed results in the past, however after the bump to LLVM 17, the results now seem pretty [incredible](https://github.com/rust-lang/rust/pull/115554#issuecomment-1706518199). Instruction counts, cycles, wall time, max RSS and even artifact sizes see large improvements. The last [try build](https://github.com/rust-lang-ci/rust/actions/runs/6077686494/job/16487768049) with this setting took 1h 8m, which is basically the same duration for try builds that we have seen recently. So there shouldn't be any large hit to CI/build time. I hope that this could potentially also reduce codegen noise of `rustc` a little bit, since small changes within a single `rustc` crate should no longer perturb optimizations because of CGU movement. We still do cross-crate LTO, so it won't eliminate it though. r? `@Mark-Simulacrum` commit c16823d757b376f90c5f5cbd542ce83235befbc4 Merge: 7c3eeb92a5f bcba369004c Author: bors Date: Sun Oct 1 11:06:38 2023 +0000 Auto merge of #116311 - matthiaskrgr:rollup-7r5zogb, r=matthiaskrgr Rollup of 3 pull requests Successful merges: - #116292 (warn if source is not either a git clone or a dist tarball) - #116295 (Fix `core::mem::drop` docs inaccuracy) - #116299 (Update location of `auxiliary/lint-plugin-test.rs`) r? `@ghost` `@rustbot` modify labels: rollup commit 2369adc5d802f2d2d49b0dbd1cea7dc1fae3c4db Author: Nicholas Nethercote Date: Fri Sep 29 20:35:32 2023 +1000 Remove unnecessary `pub`s. commit ddb742225ac76f38ea415f2b7cf1b727f9e0812d Author: Nicholas Nethercote Date: Fri Sep 29 19:54:40 2023 +1000 Rename two parsing closures. To match `parse_address_space` and `parse_bits` above. commit 86ecfdd605a76a1e4c22bcc546d7868f9c0b9d2c Author: Nicholas Nethercote Date: Fri Sep 29 19:45:59 2023 +1000 Minor comment and whitespace tweaks. commit 82d23a6275f3476f5f9520dac07b218872a9cd2b Author: Rémy Rakic Date: Mon Sep 25 19:27:48 2023 +0000 bootstrap: copy self-contained linking components to stage0-sysroot otherwise bootstrap will fail to link the stdlib on a target using the self-contained linker: rust-lld will not be found since it's currently not in the stage0-sysroot. commit bcba369004cbb68d384d42c40eaee9a906b20800 Merge: de7053133a3 544d2b370e1 Author: Matthias Krüger Date: Sun Oct 1 12:18:12 2023 +0200 Rollup merge of #116299 - emmanuel-ferdman:wip, r=albertlarsan68 Update location of `auxiliary/lint-plugin-test.rs` **PR Summary**: PR updates the location of `auxiliary/lint-plugin-test.rs` file which was moved in PR #110478. commit de7053133a32c3c442ba2f34ee84f266fd3ae969 Merge: cb4e2994c28 bc3c4457647 Author: Matthias Krüger Date: Sun Oct 1 12:18:12 2023 +0200 Rollup merge of #116295 - asquared31415:mem_drop_docs, r=WaffleLapkin Fix `core::mem::drop` docs inaccuracy r? `@Nilstrieb` commit cb4e2994c28ebe7a6a6685723573005b38855026 Merge: 7c3eeb92a5f 88e7718ec38 Author: Matthias Krüger Date: Sun Oct 1 12:18:11 2023 +0200 Rollup merge of #116292 - onur-ozkan:warn-wrong-sources, r=clubby789 warn if source is not either a git clone or a dist tarball When the repository is downloaded directly via HTTP(as in #115041), builds may fail due to missing submodules. This PR adds a check that warns people in such cases. commit 7326cd98b91851f9236fc1a688ef3c37cd1c52c6 Author: Nicholas Nethercote Date: Fri Sep 29 16:54:48 2023 +1000 Factor out the two `entry_point_type` functions. They are very similar, and each one has a comment about the importance of being kept in sync with the other. This commit removes the duplication. commit 7c3eeb92a5f337be709f5d3f59522db8750a5f2f Merge: 8fa7bdf191d 6687c075dfb Author: bors Date: Sun Oct 1 07:43:21 2023 +0000 Auto merge of #116307 - RalfJung:miri, r=RalfJung Miri subtree update r? `@ghost` commit 3169423ce9e8e304ab1badca364bc7f71d89430d Merge: ad0b7ed61f7 b5941a2fd5f Author: bors Date: Sun Oct 1 05:56:47 2023 +0000 Auto merge of #115670 - Zoxc:outline-panic-macro-1, r=Mark-Simulacrum Partially outline code inside the panic! macro This outlines code inside the panic! macro in some cases. This is split out from https://github.com/rust-lang/rust/pull/115562 to exclude changes to rustc. commit 8fa7bdf191d8658e5ab670766ac0b2d40c7d83c2 Merge: 361096fa4b7 6a02baaa3d9 Author: bors Date: Sun Oct 1 05:56:47 2023 +0000 Auto merge of #115670 - Zoxc:outline-panic-macro-1, r=Mark-Simulacrum Partially outline code inside the panic! macro This outlines code inside the panic! macro in some cases. This is split out from https://github.com/rust-lang/rust/pull/115562 to exclude changes to rustc. commit 6687c075dfb861f0c51439a34d9bd674b7ef54a9 Author: Ralf Jung Date: Sun Oct 1 07:03:42 2023 +0200 update lockfile commit 361096fa4b77e7fd9effec0a7feef139565d7a25 Merge: 18f02991535 be50413ef00 Author: bors Date: Sun Oct 1 04:00:34 2023 +0000 Auto merge of #116225 - Kobzol:newbors-integration, r=Mark-Simulacrum Add integration for new bors I think that the best way to test the [new bors](https://github.com/rust-lang/bors/tree/staging) implementation is to start using it in the wild. This PR integrates this repo with the bot (some more integration has to be done externally through GitHub). For now, I would suggest to integrate it e.g. under the ``@borsnew`` name, and start testing its try build functionality. The bot cannot do merges or approvals yet, and it doesn't touch `master` in any way, so hopefully it shouldn't cause any troubles for this repo. r? `@Mark-Simulacrum` commit e683e3eeac5603296c328ff45c9e5bb911327756 Author: Victor Song Date: Sat Sep 30 22:57:54 2023 -0500 Don't lint `manual_non_exhaustive` when enum explicitly marked as `non_exhaustive` There are cases where users create a unit variant for the purposes of tracking the number of variants for an nonexhaustive enum. We should check if an enum is explicitly marked as nonexhaustive before reporting `manual_non_exhaustive` in these cases. Fixes #11583 commit 3de082497e4581cb8ba977511dfacc848cffef37 Author: Zalathar Date: Thu Sep 28 15:08:11 2023 +1000 coverage: Regression test for functions with unreachable bodies commit 18f02991535620211f075e2165f72ec8b64338ce Merge: b11431edc14 a89cfc1dd1a Author: bors Date: Sun Oct 1 02:09:48 2023 +0000 Auto merge of #116302 - Mark-Simulacrum:bump-version, r=Mark-Simulacrum Bump to 1.75.0 Step 1 of the [release process](https://forge.rust-lang.org/release/process.html#bump-the-stable-version-number-t-6-days-friday-the-week-before). commit b11431edc141295682783e1eaf19633aa2fab6b9 Merge: ca62d2c4456 863d2fddd79 Author: bors Date: Sun Oct 1 00:25:26 2023 +0000 Auto merge of #116108 - onur-ozkan:support-make-jobs-flag, r=Mark-Simulacrum Pass `-jN` from Make to `BOOTSTRAP_ARGS` Enables the same functionality as `x -jN` in Make by passing the `-jN` arg from Make to the `BOOTSTRAP_ARGS` if it is specified. commit a89cfc1dd1a04ae5298e0faf01ac551b7d8978d2 Author: Mark Rousskov Date: Sat Sep 30 19:09:22 2023 -0400 Bump to 1.75.0 commit 884af362f2d1eeda44af46443d9f78037078192f Author: Raekye Date: Wed Sep 27 17:25:31 2023 -0400 Validate `~const` trait bounds on associated fns. Previously, any associated function could have `~const` trait bounds on generic parameters, which could lead to ICEs when these bounds were used on associated functions of non-`#[const_trait] trait` or non-`impl const` blocks. Includes changes as per @fee1-dead's comments in #116210. commit 0a6d794d0bc8872a935be4179aa3c2da33708c40 Author: Nadrieril Date: Fri Sep 29 19:44:12 2023 +0200 Cleanup number literal evaluation commit d6e9b321b3f3de5fafb4cfd2b6a5af75197df657 Author: Nadrieril Date: Fri Sep 29 17:43:06 2023 +0200 No need to carry `bias` in `IntRange` commit fac50e8fb333a6a23e0bcbd6bd612860e8ad1b62 Author: Nadrieril Date: Fri Sep 29 18:33:07 2023 +0200 Evaluate float consts eagerly commit ca62d2c445628587660ae48013f460b08b1f5552 Merge: 2f89c414f2e ea026f93d69 Author: bors Date: Sat Sep 30 21:38:54 2023 +0000 Auto merge of #116160 - MaxHearnden:quote-syntax-check, r=Mark-Simulacrum quote argument to sh -n This prevents glob expansion (*.py) and field splitting commit ea4a98369aacc19e750b0959c069026a2c28816c Merge: a4561491876 119113114cf Author: bors Date: Sat Sep 30 21:33:44 2023 +0000 Auto merge of #3097 - RalfJung:rustup, r=RalfJung Rustup commit 119113114cfe77ccec1fd69d6b6fd42422181978 Author: Ralf Jung Date: Sat Sep 30 23:32:13 2023 +0200 clippy commit 45d5733ccbd6300ece6b7bf18111e4a5b4daf774 Author: Ralf Jung Date: Sat Sep 30 23:30:51 2023 +0200 fmt commit 9a86bba8310595bc5ae3369a23dca3eddf3141b7 Merge: d6283386150 bb6c66be379 Author: Ralf Jung Date: Sat Sep 30 23:29:17 2023 +0200 Merge from rustc commit d62833861500038cdceb3259fece79d9a9b67e9f Author: Ralf Jung Date: Sat Sep 30 23:29:13 2023 +0200 Preparing for merge from rustc commit 544d2b370e141afd668a8c08e878b7f300acbe58 Author: Emmanuel Ferdman Date: Sat Sep 30 23:45:32 2023 +0300 Update location of `language-features/plugin.md` commit 13e58755d7c692c48e78faa68989e66473708119 Author: Ralf Jung Date: Sat Sep 30 22:33:22 2023 +0200 add some docs to hooks/mod.rs commit a4561491876e1ceffd177652b94e4db093e5b555 Merge: 935ced529d9 2c13713de46 Author: bors Date: Sat Sep 30 20:29:22 2023 +0000 Auto merge of #3086 - eduardosm:x86-sse3-intrinsics, r=RalfJung Implement SSE3 and SSSE3 intrinsics commit 2f89c414f2e3a05f104012b860c27338258f5382 Merge: bb6c66be379 b0412d597e7 Author: bors Date: Sat Sep 30 19:49:34 2023 +0000 Auto merge of #116157 - the8472:doc-monotonoic-suspend, r=Mark-Simulacrum Document that Instant may or may not include system-suspend time Since people are still occasionally surprised by this let's make it more explicit. This doesn't add any new guarantees, only documents the status quo. Related issues: #87906 #79462 commit 0e43a04fabc734226eb31442706f3816ffc84a6a Merge: b00236d7f05 8eb586d1549 Author: bors Date: Sat Sep 30 18:43:37 2023 +0000 Auto merge of #11587 - y21:into_iter_without_iter, r=Jarcho new lint: `into_iter_without_iter` Closes #9736 (part 2) This implements the other lint that my earlier PR missed: given an `IntoIterator for &Type` impl, check that there exists an inherent `fn iter(&self)` method. changelog: new lint: `into_iter_without_iter` r? `@Jarcho` since you reviewed #11527 I figured it makes sense for you to review this as well? commit bc3c445764769fa2f318304c8353d9fba832f466 Author: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sat Sep 30 14:41:56 2023 -0400 mem::drop docs commit bb6c66be3793ac5c738eeac91ecdc4b99388d0b4 Merge: 05c622138cd 350ead87205 Author: bors Date: Sat Sep 30 18:00:23 2023 +0000 Auto merge of #116127 - onur-ozkan:sanity-checks-on-install, r=Mark-Simulacrum add sanity checks for user write access on `x install` Resolves #113580 commit 8eb586d1549236be3ba55b205c9dc19e9bfe7f3d Author: y21 <30553356+y21@users.noreply.github.com> Date: Sat Sep 30 03:00:34 2023 +0200 new lint: `into_iter_without_iter` commit 88e7718ec38bee9dfd16e9fc37896a637a33b1ae Author: onur-ozkan Date: Sat Sep 30 20:03:26 2023 +0300 warn if source is not either a git clone or a dist tarball Signed-off-by: onur-ozkan commit 05c622138cd47f03a5f6aaabbf0828bc378c5f3a Merge: 75d731eee97 1008c984059 Author: bors Date: Sat Sep 30 16:05:49 2023 +0000 Auto merge of #116286 - ouz-a:merge_my_commits, r=Mark-Simulacrum Add Oğuz Ağcayazı to .mailmap this will merge my commits under one name (hopefully) commit 133aa56a84a4d52a066c4fbf12b53314310e91e1 Author: linkmauve Date: Sat Sep 30 17:56:42 2023 +0200 Add missing #[inline] on AsFd impl for sys::unix::fs::File This operation should be extremely cheap, at most the mov of the underlying file descriptor, but due to this missing #[inline] it is currently a function call. commit d5cc97e32c9b1919a175aa798e99bd7dde814073 Author: koka Date: Sun Oct 1 00:47:57 2023 +0900 Add macro for test which use std internally commit 935ced529d9473cabd9f2274527a808e42bbc4d7 Merge: a2395767f46 97bb8c80ed7 Author: bors Date: Sat Sep 30 15:33:42 2023 +0000 Auto merge of #3096 - sthibaul:master, r=RalfJung Bump libloading to 0.8 commit 44b6aca96b48299adf0ab44307c40d7f3392d060 Author: koka Date: Sat Sep 30 23:56:11 2023 +0900 Avoid linting in external/proc macro commit 97bb8c80ed79f74bf669ffebef53326d1fc1aabb Author: Samuel Thibault Date: Sat Sep 30 15:49:40 2023 +0200 Bump libloading to 0.8 commit 999a354a81e472e43670b21f4101179243ba79cd Author: ouz-a Date: Sat Sep 30 16:52:10 2023 +0300 add span to terminator commit 9130484db91e609686e287f7547fc7c085068d9b Author: ouz-a Date: Sat Sep 30 16:40:15 2023 +0300 create localdecl and add span to it commit ad0b7ed61f7ae352c3d69a02a00b30a28acce63f Merge: 1a82ca0a61c a4d11d936ec Author: bors Date: Sat Sep 30 12:38:12 2023 +0000 Auto merge of #116254 - WaffleLapkin:nicen-traversal, r=cjgillot Assorted improvements for `rustc_middle::mir::traversal` r? `@cjgillot` I'm not _entirely_ sure about all changes, although I do like all of them. If you'd like I can drop some commits. Best reviewed on a commit-by-commit basis, I think, since they are fairly isolated. commit 75d731eee97b300b3cbd13222fe17c34b15f006a Merge: 5282e5e1201 814fbd89b69 Author: bors Date: Sat Sep 30 12:38:12 2023 +0000 Auto merge of #116254 - WaffleLapkin:nicen-traversal, r=cjgillot Assorted improvements for `rustc_middle::mir::traversal` r? `@cjgillot` I'm not _entirely_ sure about all changes, although I do like all of them. If you'd like I can drop some commits. Best reviewed on a commit-by-commit basis, I think, since they are fairly isolated. commit 1008c984059b4b34df40a8dd3fd77c249b7df6b7 Author: ouz-a Date: Sat Sep 30 14:08:52 2023 +0300 Add Oğuz Ağcayazı to .mailmap commit 2c13713de462f5464d40056940f4e69140208a46 Author: Eduardo Sánchez Muñoz Date: Tue Sep 26 21:12:45 2023 +0200 Implement `llvm.x86.ssse3.*` intrinsics commit 4b2b0eaff239c630242bd44552fba3125b1f59c5 Author: Eduardo Sánchez Muñoz Date: Tue Sep 26 19:45:06 2023 +0200 Implement `llvm.x86.sse3.*` intrinsics commit 5282e5e120128ba589728ee4bcb4f18511ba9fb0 Merge: 177091258c0 841bff2e29c Author: bors Date: Sat Sep 30 09:18:06 2023 +0000 Auto merge of #116195 - fmease:rustdoc-investigate-perf-regression, r=GuillaumeGomez rustdoc: speed up processing of cross-crate fns to fix a perf regression * The first commit doesn't affect perf but get's rid of a `.clone()` and a bunch of lines of code. I can drop it if you'd like me to * The second commit, *“reduce the amount of `asyncness` query executions”*, addresses the perf regression introduced in #116084 r? `@ghost` commit 177091258c039398d30137b52e1c575a98aa7597 Merge: 9136560d324 1ad3bb971b3 Author: bors Date: Sat Sep 30 05:53:30 2023 +0000 Auto merge of #116280 - weihanglo:update-cargo, r=weihanglo Update cargo 4 commits in e6aabe8b3fcf639be3a5bf68e77853bd7b3fa27d..59596f0f31a94fde48b5aa7e945cd0b7ceca9620 2023-09-26 16:31:53 +0000 to 2023-09-29 19:29:17 +0000 - refactor: Switch from termcolor to anstream (rust-lang/cargo#12751) - Add missing `strip` entries in `dev` and `release` profiles. (rust-lang/cargo#12748) - Add better suggestion for the unsupported silent flag (rust-lang/cargo#12723) - docs(ref): Establish publish best practices (rust-lang/cargo#12745) r? ghost commit ffa2d3ab632bd02403a31059f58c513c53513fa8 Author: Ralf Jung Date: Fri Sep 29 22:38:52 2023 +0200 dont call mir.post_mono_checks in codegen commit acb7c21507f4c6f7247e702287ab4caf64b31235 Author: Ralf Jung Date: Fri Sep 29 22:38:52 2023 +0200 dont call mir.post_mono_checks in codegen commit 81d219a27da790e44568364dc6136af34cb9933b Merge: 809cd20618c 6fd5dc8860d Author: bors Date: Sat Sep 30 04:05:26 2023 +0000 Auto merge of #115933 - oli-obk:simd_shuffle_const, r=workingjubilee Prototype using const generic for simd_shuffle IDX array cc https://github.com/rust-lang/rust/issues/85229 r? `@workingjubilee` on the design TLDR: there is now a `fn simd_shuffle_generic(x: T, y: T) -> U;` intrinsic that allows replacing ```rust simd_shuffle(a, b, const { stuff }) ``` with ```rust simd_shuffle_generic::<_, _, {&stuff}>(a, b) ``` which makes the compiler implementations much simpler, if we manage to at some point eliminate `simd_shuffle`. There are some issues with this today though (can't do math without bubbling it up in the generic arguments). With this change, we can start porting the simple cases and get better data on the others. commit 9136560d32440cc7cc0ab78353054c90648c070c Merge: 4efd65571e7 a9030e66886 Author: bors Date: Sat Sep 30 04:05:26 2023 +0000 Auto merge of #115933 - oli-obk:simd_shuffle_const, r=workingjubilee Prototype using const generic for simd_shuffle IDX array cc https://github.com/rust-lang/rust/issues/85229 r? `@workingjubilee` on the design TLDR: there is now a `fn simd_shuffle_generic(x: T, y: T) -> U;` intrinsic that allows replacing ```rust simd_shuffle(a, b, const { stuff }) ``` with ```rust simd_shuffle_generic::<_, _, {&stuff}>(a, b) ``` which makes the compiler implementations much simpler, if we manage to at some point eliminate `simd_shuffle`. There are some issues with this today though (can't do math without bubbling it up in the generic arguments). With this change, we can start porting the simple cases and get better data on the others. commit 6ef3fd713862c0deecc4a62390be6cf26866673f Author: cui fliter Date: Sat Sep 30 10:26:04 2023 +0800 Fix broken links Signed-off-by: cui fliter commit 4efd65571e7ad62ca2cfb86271e7c6af192032ce Merge: b8b376a2877 4c2f1c615b9 Author: bors Date: Sat Sep 30 02:15:19 2023 +0000 Auto merge of #115546 - SUPERCILEX:patch-2, r=Amanieu Weaken needlessly restrictive orderings on Arc::*_count Follow up to https://github.com/rust-lang/rust/pull/95183 from this zulip: https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Why.20does.20Arc.3A.3Astrong_count.20use.20Acquire.20instead.20of.20Relaxed.3F/near/386213850 I'd like to use the strong_count for a lockless algorithm I'm writing, but I don't need acquire semantics so that's pointlessly restrictive on arm/risc-v. commit 1ad3bb971b3d47fe4cbf18ecd9d1f1963cc4676b Author: Weihang Lo Date: Sat Sep 30 09:06:06 2023 +0800 Update cargo commit b8b376a2877f6d3d9529a3dee9c0e2fe29147468 Merge: 8ce4540bd6f d185e0d8992 Author: bors Date: Sat Sep 30 00:33:43 2023 +0000 Auto merge of #115368 - loongarch-rs:none-tier2, r=pietroalbini Promote loongarch64-unknown-none* to Tier 2 MCP: https://github.com/rust-lang/compiler-team/issues/664 commit 841bff2e29c13b755fbb8cb9e0fc9a1555f75706 Author: León Orell Valerian Liehr Date: Fri Sep 29 23:04:53 2023 +0200 rustdoc: reduce the amount of `asyncness` query executions commit 854cdff9722e275496d15d8a89aa55ee32e753cb Author: León Orell Valerian Liehr Date: Fri Sep 29 19:17:55 2023 +0200 rustdoc: simplify sugared_async_return_type commit 8ce4540bd6fe7d58d4bc05f1b137d61937d3cf72 Merge: 56ada88e7e1 3ee2c526df8 Author: bors Date: Fri Sep 29 20:31:52 2023 +0000 Auto merge of #116275 - matthiaskrgr:rollup-prx5fto, r=matthiaskrgr Rollup of 6 pull requests Successful merges: - #112123 (fix(suggestion): insert projection to associated types) - #116024 (Implement Region for smir) - #116030 (run abi/compatibility test against a whole bunch of targets) - #116216 (ci: upgrade to crosstool-ng 1.26.0) - #116241 (Add Exclusive forwarding impls (FnOnce, FnMut, Generator)) - #116263 (More fixes for running the test suite on a bare metal target) r? `@ghost` `@rustbot` modify labels: rollup commit 3ee2c526df8458d6152ff67fd8d344fe6fdf2391 Merge: 4db2b741c88 3853774df8d Author: Matthias Krüger Date: Fri Sep 29 22:27:52 2023 +0200 Rollup merge of #116263 - ferrocene:pa-more-bare-metal-fixes, r=oli-obk More fixes for running the test suite on a bare metal target This PR adds more fixes needed to run the test suite on bare metal targets (in this case, without unwinding and with static relocations). There is no CI job exercising tests without unwinds, but I can confirm this worked in Ferrocene's CI. commit 4db2b741c88a51a0b28179cd6e71589a22d73a7a Merge: 60ba6b494a6 a95f20c9adb Author: Matthias Krüger Date: Fri Sep 29 22:27:51 2023 +0200 Rollup merge of #116241 - dtolnay:exclusivefwd, r=Amanieu Add Exclusive forwarding impls (FnOnce, FnMut, Generator) This is adapted from #104057. commit 60ba6b494a6bbd0430fb10efd225915a69297fbe Merge: 77e9dcd3c83 f99fdac3df5 Author: Matthias Krüger Date: Fri Sep 29 22:27:51 2023 +0200 Rollup merge of #116216 - heiher:crosstool, r=Kobzol ci: upgrade to crosstool-ng 1.26.0 This PR upgrades our builders from crosstool-ng 1.25.0 to 1.26.0. Except for LoongArch64 and RISC-V 64, which have minor version upgrades, other architectures have not changed. commit 77e9dcd3c83a4a84f845a2af323e7235e80e9996 Merge: 26be5754c6c ec188115578 Author: Matthias Krüger Date: Fri Sep 29 22:27:50 2023 +0200 Rollup merge of #116030 - RalfJung:abi-compat-test, r=wesleywiser run abi/compatibility test against a whole bunch of targets commit 26be5754c6c1f70b892d5214c090b723df88e0fc Merge: 4a886462c92 34f10e2ab98 Author: Matthias Krüger Date: Fri Sep 29 22:27:50 2023 +0200 Rollup merge of #116024 - ouz-a:smir_region, r=oli-obk Implement Region for smir Adds Region and it's relevant types to smir and covers them with stable implementation r? `@oli-obk` commit 4a886462c92ae7636c4d8cd1f74e1b1d5fac7302 Merge: 56ada88e7e1 b83dfb5c5a6 Author: Matthias Krüger Date: Fri Sep 29 22:27:49 2023 +0200 Rollup merge of #112123 - bvanjoi:fix-98562, r=compiler-errors fix(suggestion): insert projection to associated types Fixes #98562 This PR has fixed some help suggestions for unsupported syntax, such as `fn f(_:T) where T: IntoIterator, std::iter::IntoIterator::Item = () {}` to `fn f>(_T) {}`. commit 814fbd89b69173a3f2189c739dd32921702c5eca Author: Maybe Waffle Date: Fri Sep 29 09:58:53 2023 +0000 Remove deleted docs + better link together MIR traversing docs commit b00236d7f0537b22794be838064c944a36e85c70 Merge: 67a83ff0576 2d2017942af Author: bors Date: Fri Sep 29 18:49:57 2023 +0000 Auto merge of #11580 - y21:issue11579, r=Jarcho [`manual_let_else`]: only omit block if span is from same ctxt Fixes #11579. The lint already had logic for omitting a block in `else` if a block is already present, however this didn't handle the case where the block is from a different expansion/syntax context. E.g. ```rs macro_rules! panic_in_block { () => { { panic!() } } } let _ = match Some(1) { Some(v) => v, _ => panic_in_block!() }; ``` It would see this in its expanded form as `_ => { panic!() }` and think it doesn't have to include a block in its suggestion because it is already there, however that's not true if it's from a different expansion like in this case. changelog: [`manual_let_else`]: only omit block in suggestion if the block is from the same expansion commit 06d9602d3310c2001f1fa9c15e2d502cad36dfc5 Author: Michael Goulet Date: Fri Sep 29 18:36:20 2023 +0000 Only trigger refine lint on reachable traits commit 56ada88e7e1f00e6c6e8a0957de295bc0e2d64f7 Merge: a6dfd89fa76 72e29da3ecc Author: bors Date: Fri Sep 29 15:51:48 2023 +0000 Auto merge of #113301 - Be-ing:stabilize_bundle_whole-archive, r=petrochenkov stabilize combining +bundle and +whole-archive link modifiers Per discussion on https://github.com/rust-lang/rust/issues/108081 combining +bundle and +whole-archive already works and can be stabilized independently of other aspects of the packed_bundled_libs feature. There is no risk of regression because this was not previously allowed. r? `@petrochenkov` commit a2395767f46a421f5254095f4d3950729cd3cd16 Merge: 7619edbe7a1 0c0c088e57c Author: bors Date: Fri Sep 29 15:26:51 2023 +0000 Auto merge of #3093 - eduardosm:llvm.x86.sse2.pmadd.wd, r=RalfJung Implement the `llvm.x86.sse2.pmadd.wd` intrinsic commit 2d2017942afc221da0295962ac0374bd31cc6d1c Author: y21 <30553356+y21@users.noreply.github.com> Date: Thu Sep 28 16:31:21 2023 +0200 [`manual_let_else`]: only omit block if span is from same ctxt commit 0c0c088e57c2dbb7a4145bf2bee1ca1cc137bf50 Author: Eduardo Sánchez Muñoz Date: Thu Sep 28 18:13:59 2023 +0200 Implement the `llvm.x86.sse2.pmadd.wd` intrinsic commit a6dfd89fa76e5dda36d07463d0e54268d6240b49 Merge: c5450191f31 9b7f9c4328d Author: bors Date: Fri Sep 29 13:53:11 2023 +0000 Auto merge of #113797 - RalfJung:offset_from_docs, r=workingjubilee offset_from: docs improvements This is the part of https://github.com/rust-lang/rust/pull/112837 that doesn't add a new function, just tweaks the existing docs. commit 3853774df8d8217fb9788be3c0636b9a06da740f Author: Pietro Albini Date: Wed Jun 14 12:19:21 2023 +0200 mark relevant tests as requiring unwinding commit c5450191f313658d206dc7539311f665a274947f Merge: a66e334bc5c 0031cf7c7e5 Author: bors Date: Fri Sep 29 11:59:51 2023 +0000 Auto merge of #115759 - oli-obk:open_drop_from_non-ADT, r=lcnr Reveal opaque types before drop elaboration fixes https://github.com/rust-lang/rust/issues/113594 r? `@cjgillot` cc `@JakobDegen` This pass was introduced in https://github.com/rust-lang/rust/pull/110714 I moved it before drop elaboration (which only cares about the hidden types of things, not the opaque TAIT or RPIT type) and set it to run unconditionally (instead of depending on the optimization level and whether the inliner is active) commit 90f317b2de742bcc986cd40c6736ffc3813d036c Author: Pietro Albini Date: Fri Sep 29 12:24:35 2023 +0200 add needs-relocation-model-pic to compiletest commit b83dfb5c5a6e9c976200490c89ff00726c425ad2 Author: bohan Date: Wed May 31 10:10:16 2023 +0800 fix(suggestion): insert projection to associated types commit aac29a0fc3b9ab7d3784a7d5b637cf51a01b0469 Author: lcnr Date: Fri Sep 29 11:47:42 2023 +0200 specialization: use clause commit a4f6770d83cb5aa82f10d8e8441ca5708600b077 Author: lcnr Date: Fri Sep 29 11:34:50 2023 +0200 a small wf and clause cleanup commit a66e334bc5c5395907dddfc6211cbb110c44576d Merge: b8536c1aa19 95262e46020 Author: bors Date: Fri Sep 29 09:23:45 2023 +0000 Auto merge of #116260 - matthiaskrgr:rollup-q3sge0i, r=matthiaskrgr Rollup of 7 pull requests Successful merges: - #116133 (ref(bootstrap.py): add `eprint` function) - #116201 (Fix `noop_method_call` detection) - #116231 (Remove `rustc_lint_defs::lint_array`) - #116234 (Miri subtree update) - #116239 (Only visit reachable nodes in SsaLocals.) - #116245 (Clippy backport: Move needless_raw_string_hashes to pedantic) - #116253 (Make `adt_const_params` feature suggestion consistent with other features and improve when it is emitted) r? `@ghost` `@rustbot` modify labels: rollup commit 67a83ff0576488faf22ee73d40d3c3590c832224 Merge: d38fa1a32dd ad5653b296e Author: bors Date: Fri Sep 29 09:09:52 2023 +0000 Auto merge of #11582 - DaniPopes:missing-headers, r=xFrednet Add missing lint description headers Discovered in https://github.com/rust-lang/rust-analyzer/pull/15680/files#diff-7cb229b5139c72b6c230e3c195be375724c92226421fd57d5cf08872503e8c27L214-R226 changelog: none commit 95262e460206031bd99faba80942a23b20c44383 Merge: 92234f949a2 b53a1b38089 Author: Matthias Krüger Date: Fri Sep 29 10:11:15 2023 +0200 Rollup merge of #116253 - asquared31415:adt_const_params_feature, r=compiler-errors Make `adt_const_params` feature suggestion consistent with other features and improve when it is emitted Makes the suggestion to add `adt_const_params` formatted like every other feature gate (notably this makes it such that the playground recognizes it). Additionally improves the situations in which that help is emitted so that it's only emitted when the type would be valid or the type *could* be valid (using a slightly incorrect heuristic that favors suggesting the feature over not) instead of, for example, implying that adding the feature would allow the use of `String`. Also adds the "the only supported types are integers, `bool` and `char`" note to the errors on fn and raw pointers. r? `@compiler-errors` commit 1a82ca0a61c558f0fc7409b248f875df21282cfd Merge: 38fd80a1123 82207f4ff4a Author: Matthias Krüger Date: Fri Sep 29 10:11:14 2023 +0200 Rollup merge of #116245 - flip1995:clippy-backport, r=Manishearth Clippy backport: Move needless_raw_string_hashes to pedantic Really small backport this time. Context: https://github.com/rust-lang/rust-clippy/pull/11415#issuecomment-1739880932 I'd rather get this in 1.74 than waiting another release cycle. r? `@Manishearth` cc `@Mark-Simulacrum` This should be merged before beta is branched tomorrow. commit 92234f949a2d8a4d7a20c03cae82ff2ccd008f79 Merge: 4f09f80bcf3 07f81cd58ae Author: Matthias Krüger Date: Fri Sep 29 10:11:14 2023 +0200 Rollup merge of #116245 - flip1995:clippy-backport, r=Manishearth Clippy backport: Move needless_raw_string_hashes to pedantic Really small backport this time. Context: https://github.com/rust-lang/rust-clippy/pull/11415#issuecomment-1739880932 I'd rather get this in 1.74 than waiting another release cycle. r? `@Manishearth` cc `@Mark-Simulacrum` This should be merged before beta is branched tomorrow. commit 4f09f80bcf31bac53bd1abf106bdbea6ee39a29c Merge: 1ed00fe491a 3816c15b886 Author: Matthias Krüger Date: Fri Sep 29 10:11:14 2023 +0200 Rollup merge of #116239 - cjgillot:issue-116212, r=WaffleLapkin Only visit reachable nodes in SsaLocals. Fixes https://github.com/rust-lang/rust/issues/116212 commit 1ed00fe491ae2ae55ee6db4d7eb61f3fee0e2d9c Merge: 0c450184739 e0f4ab84a7e Author: Matthias Krüger Date: Fri Sep 29 10:11:13 2023 +0200 Rollup merge of #116234 - RalfJung:miri, r=RalfJung Miri subtree update r? `@ghost` commit 0c4501847394fd89d9fb39ee601e1ae6bb9da264 Merge: e814f1e3c01 f1b74841602 Author: Matthias Krüger Date: Fri Sep 29 10:11:13 2023 +0200 Rollup merge of #116231 - DaniPopes:simpler-lint-array, r=Nilstrieb Remove `rustc_lint_defs::lint_array` commit e814f1e3c0188ea8fc583bc35a63d2c7d9935c17 Merge: f777e8cf22c 66bc682caba Author: Matthias Krüger Date: Fri Sep 29 10:11:12 2023 +0200 Rollup merge of #116201 - Jarcho:noop_fix, r=fee1-dead Fix `noop_method_call` detection This needs to be merged before #116198 can compile. The error occurs before the compiler is built so this needs to be a separate PR. commit f777e8cf22c5094e2f0801a50b1057de7b0e1606 Merge: c1f86f0bc87 598f11a1eeb Author: Matthias Krüger Date: Fri Sep 29 10:11:12 2023 +0200 Rollup merge of #116133 - pouriya:refactor-bootstrap.py, r=albertlarsan68 ref(bootstrap.py): add `eprint` function Implemented a 3-line function called `eprint` which is just like `print` but for `stderr`. So each `print(..., file=sys.stderr)` becomes `eprint(...)`.
Testing `eprint` function: ```sh $ cat eprint.py ``` ```python import sys def eprint(*args, **kwargs): kwargs['file'] = sys.stderr print(*args, **kwargs) eval('eprint({})'.format(sys.argv[1])) ``` ```sh $ python3 eprint.py '"hello"' hello $ ``` ```sh $ python3 eprint.py '"hello"' 2>/dev/null $ ``` ```sh $ python3 eprint.py '"hello", "world", flush=True, file=sys.stdout' hello world $ ``` ```sh $ python3 eprint.py '"hello", "world", flush=True, file=sys.stdout' 2>/dev/null $ ``` commit 373cc2160a4bdf2c29b2a9620c5992dcc77eb4cb Author: Nicholas Nethercote Date: Fri Sep 29 16:47:47 2023 +1000 Change `depth` arg to `at_root`. This will facilitate a subsequent refactoring. commit b8536c1aa1973dd2438841815b1eeec129480e45 Merge: c1f86f0bc87 25648de28f1 Author: bors Date: Fri Sep 29 07:35:44 2023 +0000 Auto merge of #116176 - FedericoStra:isqrt, r=dtolnay Add "integer square root" method to integer primitive types For every suffix `N` among `8`, `16`, `32`, `64`, `128` and `size`, this PR adds the methods ```rust const fn uN::isqrt() -> uN; const fn iN::isqrt() -> iN; const fn iN::checked_isqrt() -> Option; ``` to compute the [integer square root](https://en.wikipedia.org/wiki/Integer_square_root), addressing issue #89273. The implementation is based on the [base 2 digit-by-digit algorithm](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)) on Wikipedia, which after some benchmarking has proved to be faster than both binary search and Heron's/Newton's method. I haven't had the time to understand and port [this code](http://atoms.alife.co.uk/sqrt/SquareRoot.java) based on lookup tables instead, but I'm not sure whether it's worth complicating such a function this much for relatively little benefit. commit c1f86f0bc87eaa0cf16bcf3de38793096ec4db94 Merge: a327e753bc8 d00c7e78ea9 Author: bors Date: Fri Sep 29 05:45:18 2023 +0000 Auto merge of #116089 - estebank:issue-115992-2, r=compiler-errors When suggesting `self.x` for `S { x }`, use `S { x: self.x }` Fix #115992. r? `@compiler-errors` Follow up to #116086. commit 7619edbe7a1a100851ce0b573a589709297c7b23 Merge: 6ef11ddc3bd 71030bae753 Author: bors Date: Fri Sep 29 05:35:40 2023 +0000 Auto merge of #3094 - RalfJung:float, r=RalfJung add some float tests Fixes https://github.com/rust-lang/miri/issues/2649 commit 71030bae75307ea174cbf31a46888b584236476b Author: Ralf Jung Date: Fri Sep 29 07:31:52 2023 +0200 add FMA test that would fail with apfloat commit 2f7fdd1ee9f0473ef893fe79329429406f193893 Author: Ralf Jung Date: Fri Sep 29 07:25:22 2023 +0200 add tests for '%' sign on floats commit a327e753bc873d5f5dc1820151a6cdf3dac0a39c Merge: 60bb5192d16 bdd66b3f98e Author: bors Date: Fri Sep 29 03:57:17 2023 +0000 Auto merge of #115986 - onur-ozkan:fix-cross-compilation-lto-problem, r=wesleywiser allow LTO on `proc-macro` crates with `-Zdylib-lto` ref https://github.com/rust-lang/rust/pull/115986#issuecomment-1732316361 Fixes #110296 commit 60bb5192d169d301db9be08141d852592142d3b3 Merge: 958c2b87d89 e8b8ddd17e9 Author: bors Date: Fri Sep 29 02:09:40 2023 +0000 Auto merge of #115843 - lcnr:bb-provisional-cache, r=compiler-errors new solver: remove provisional cache The provisional cache is a performance optimization if there are large, interleaving cycles. Such cycles generally do not exist. It is incredibly complex and unsound in all trait solvers which have one: the old solver, chalk, and the new solver ([link](https://github.com/rust-lang/rust/blob/master/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs)). Given the assumption that it is not perf-critical and also incredibly complex, remove it from the new solver, only checking whether a goal is on the stack. While writing this, I uncovered two additional soundness bugs, see the inline comments for them. r? `@compiler-errors` commit d38fa1a32dd265793a64c1543de45a7d2fde0d0b Merge: 91997a4df41 330ebbb9f9e Author: bors Date: Fri Sep 29 01:58:42 2023 +0000 Auto merge of #11527 - y21:iter_without_into_iter, r=Jarcho new lint: `iter_without_into_iter` Closes #9736 A new lint that looks for `iter` (and `iter_mut`) method implementations without the type implementing `IntoIterator` for `&Type`. Imo this seems rather pedantic, so I went with that, but I can be convinced to change it to `style` like the linked issue asked for. Writing a machine applicable suggestion seems a bit tricky and tedious, so for now this relies on the user adding remaining lifetimes. changelog: new lint: `iter_without_into_iter` commit ad5653b296e8b3a001f15a3c02c5b17de8d13d57 Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri Sep 29 03:08:34 2023 +0200 Add missing lint description headers commit 958c2b87d896063de2ce405db08e40bc0bcd8cb8 Merge: 7b4d9e155fe 77e205a113e Author: bors Date: Fri Sep 29 00:24:57 2023 +0000 Auto merge of #115821 - obeis:hir-analysis-migrate-diagnostics-5, r=compiler-errors Migrate `rustc_hir_analysis` to session diagnostic [Part 5] Finishing `coherence/builtin.rs` file commit a4d11d936ec9750297734d0233e2d7dc5f8728af Author: Maybe Waffle Date: Thu Sep 28 23:50:56 2023 +0000 Reverse postorder instead of using reversed postorder commit 27242437c7315b8fd456e310fe767a152cb434cd Author: Maybe Waffle Date: Thu Sep 28 23:50:56 2023 +0000 Reverse postorder instead of using reversed postorder commit 0e0dc59acbdc4671c1fdcaf6c06fd9c4d1d8c9e2 Author: Maybe Waffle Date: Thu Sep 28 23:16:48 2023 +0000 Use `and_then` instead of while let chain to clarify `iter` scope commit e0abb98e2120903fe3a1b787914e0092150d88da Author: Maybe Waffle Date: Thu Sep 28 23:11:15 2023 +0000 Remove unnecessary `&mut/ref mut` pair commit b53a1b38089f30a34d932ad4030f3d529664c9df Author: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu Sep 28 20:51:48 2023 +0000 make adt_const_params feature suggestion more consistent with others and only suggest it when the type can probably work commit a7f3c4e6086c70f1c617bae6c157d5dc5636670f Author: Maybe Waffle Date: Thu Sep 28 22:39:53 2023 +0000 Don't resolve basic block data in `Postorder` The only usage immediately throws out the data, so. commit 0d8a45813c52c33790648b9401428087f0ecb5d2 Author: Maybe Waffle Date: Thu Sep 28 22:30:31 2023 +0000 `(&mut iter)` -> `iter.by_ref()` commit fb0e58596f9c504466676b70d1c93c910d6ba9ae Author: Maybe Waffle Date: Thu Sep 28 22:28:09 2023 +0000 Simplify `Postorder::next` commit 82e251be7da92f9f7ddfcb511b11aa8a1c33f98e Author: Maybe Waffle Date: Thu Sep 28 22:17:13 2023 +0000 Remove `ReversePostorder` altogether It was not used anywhere, instead we directly reverse postorder. commit f040210b31987e8fbe799fb1b7feeda3ab3ccc56 Author: Maybe Waffle Date: Thu Sep 28 22:15:51 2023 +0000 Remove outdated comment There is no `reset` anymore commit 7b4d9e155fec06583c763f176fc432dc779f1fc6 Merge: 1393ef1fa0a e4af4e50831 Author: bors Date: Thu Sep 28 21:35:18 2023 +0000 Auto merge of #115659 - compiler-errors:itp, r=cjgillot Stabilize `impl_trait_projections` Closes #115659 ## TL;DR: This allows us to mention `Self` and `T::Assoc` in async fn and return-position `impl Trait`, as you would expect you'd be able to. Some examples: ```rust #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] // (just needed for final tests below) // ---------------------------------------- // struct Wrapper<'a, T>(&'a T); impl Wrapper<'_, ()> { async fn async_fn() -> Self { //^ Previously rejected because it returns `-> Self`, not `-> Wrapper<'_, ()>`. Wrapper(&()) } fn impl_trait() -> impl Iterator { //^ Previously rejected because it mentions `Self`, not `Wrapper<'_, ()>`. std::iter::once(Wrapper(&())) } } // ---------------------------------------- // trait Trait<'a> { type Assoc; fn new() -> Self::Assoc; } impl Trait<'_> for () { type Assoc = (); fn new() {} } impl<'a, T: Trait<'a>> Wrapper<'a, T> { async fn mk_assoc() -> T::Assoc { //^ Previously rejected because `T::Assoc` doesn't mention `'a` in the HIR, // but ends up resolving to `>::Assoc`, which does rely on `'a`. // That's the important part -- the elided trait. T::new() } fn a_few_assocs() -> impl Iterator { //^ Previously rejected for the same reason [T::new(), T::new(), T::new()].into_iter() } } // ---------------------------------------- // trait InTrait { async fn async_fn() -> Self; fn impl_trait() -> impl Iterator; } impl InTrait for &() { async fn async_fn() -> Self { &() } //^ Previously rejected just like inherent impls fn impl_trait() -> impl Iterator { //^ Previously rejected just like inherent impls [&()].into_iter() } } ``` ## Technical: Lifetimes in return-position `impl Trait` (and `async fn`) are duplicated as early-bound generics local to the opaque in order to make sure we are able to substitute any late-bound lifetimes from the function in the opaque's hidden type. (The [dev guide](https://rustc-dev-guide.rust-lang.org/return-position-impl-trait-in-trait.html#aside-opaque-lifetime-duplication) has a small section about why this is necessary -- this was written for RPITITs, but it applies to all RPITs) Prior to #103491, all of the early-bound lifetimes not local to the opaque were replaced with `'static` to avoid issues where relating opaques caused their *non-captured* lifetimes to be related. This `'static` replacement led to strange and possibly unsound behaviors (https://github.com/rust-lang/rust/issues/61949#issuecomment-508836314) (https://github.com/rust-lang/rust/issues/53613) when referencing the `Self` type alias in an impl or indirectly referencing a lifetime parameter via a projection type (via a `T::Assoc` projection without an explicit trait), since lifetime resolution is performed on the HIR, when neither `T::Assoc`-style projections or `Self` in impls are expanded. Therefore an error was implemented in #62849 to deny this subtle behavior as a known limitation of the compiler. It was attempted by `@cjgillot` to fix this in #91403, which was subsequently unlanded. Then it was re-attempted to much success (🎉) in #103491, which is where we currently are in the compiler. The PR above (#103491) fixed this issue technically by *not* replacing the opaque's parent lifetimes with `'static`, but instead using variance to properly track which lifetimes are captured and are not. The PR gated any of the "side-effects" of the PR behind a feature gate (`impl_trait_projections`) presumably to avoid having to involve T-lang or T-types in the PR as well. `@cjgillot` can clarify this if I'm misunderstanding what their intention was with the feature gate. Since we're not replacing (possibly *invariant*!) lifetimes with `'static` anymore, there are no more soundness concerns here. Therefore, this PR removes the feature gate. Tests: * `tests/ui/async-await/feature-self-return-type.rs` * `tests/ui/impl-trait/feature-self-return-type.rs` * `tests/ui/async-await/issues/issue-78600.rs` * `tests/ui/impl-trait/capture-lifetime-not-in-hir.rs` --- r? cjgillot on the impl (not much, just removing the feature gate) I'm gonna mark this as FCP for T-lang and T-types. commit 38fd80a1123e56a24feda899ba4d2599a8d28637 Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu Sep 28 16:00:38 2023 +0200 Remove `rustc_lint_defs::lint_array` commit f1b74841602617633a9f731f5a5b20ae7d3ed117 Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu Sep 28 16:00:38 2023 +0200 Remove `rustc_lint_defs::lint_array` commit 330ebbb9f9ee3c4bab37e330726ccc3ac1c26e4a Author: y21 <30553356+y21@users.noreply.github.com> Date: Mon Sep 18 00:19:34 2023 +0200 new lint: `iter_without_into_iter` commit 1393ef1fa0a213bf570075f250364a528965ed68 Merge: 42faef503f3 1b2c1a85833 Author: bors Date: Thu Sep 28 19:44:14 2023 +0000 Auto merge of #116199 - Urgau:simplify-invalid_ref_casting, r=cjgillot Simplify some of the logic in the `invalid_reference_casting` lint This PR simplifies 2 areas of the logic for the `invalid_reference_casting` lint: - The init detection: we now use the newly added `expr_or_init` function instead of a manual detection - The ref-to-mut-ptr casting detection logic: I simplified this logic by caring less hardly about the order of the casting operations Those two simplifications permits us to detect more cases, as can be seen in the test output changes. commit ca59652866242dd574a5e59cdeeab5c8548eeb49 Author: Jakub Beránek Date: Sat Feb 4 00:04:22 2023 +0100 Build `rustc` with a single CGU on x64 Linux commit 82207f4ff4ab4712a86e152656aaf1aa6a9299c6 Author: Alex Macleod Date: Sun Aug 27 11:43:45 2023 +0000 Move needless_raw_string_hashes to pedantic commit 07f81cd58aef7529f6cf457e4167d8ce0c2c89ae Author: Alex Macleod Date: Sun Aug 27 11:43:45 2023 +0000 Move needless_raw_string_hashes to pedantic commit 91997a4df416a0d058853f353de5e4648089dbb8 Merge: d18d01a8b1d 0f198579d0f Author: bors Date: Thu Sep 28 17:59:05 2023 +0000 Auto merge of #11565 - RalfJung:mir_to_const, r=Jarcho mir_to_const improvements This simplifies some code and also fixes the float array handling to properly take into account the `offset`, and to work with little-endian targets. Fixes https://github.com/rust-lang/rust-clippy/issues/11488 changelog: none commit a95f20c9adb45be65d579251b3f7e4401b8aa3b1 Author: David Tolnay Date: Thu Sep 28 10:18:56 2023 -0700 Add Exclusive forwarding impls (FnOnce, FnMut, Generator) commit 42faef503f3e765120ca0ef06991337668eafc32 Merge: 925f8441645 b325e9c60df Author: bors Date: Thu Sep 28 17:16:47 2023 +0000 Auto merge of #116227 - nikic:update-llvm-14, r=cuviper Update LLVM submodule Update LLVM submodule to pull in additional 17.x backports. Fixes https://github.com/rust-lang/rust/issues/115970. Fixes miscompile from https://github.com/rust-lang/rust/pull/115554. Fixes miscompile from https://github.com/rust-lang/rust/pull/102099. Fixes inlining regressions mentioned at https://github.com/rust-lang/llvm-project/pull/153. commit 3816c15b88651db3c1f1b56bbd78edec11045fb0 Author: Camille GILLOT Date: Sun May 28 12:55:36 2023 +0000 Only visit reachable nodes in SsaLocals. commit 255ca184541d9f411cadfc3306ef4f6435ac4eb9 Author: Camille GILLOT Date: Thu Sep 28 17:05:52 2023 +0000 Add test for 116212. commit 34f10e2ab98622e42c38c97530070aa69ad51d86 Author: ouz-a Date: Thu Sep 28 19:52:41 2023 +0300 remove unimplemented commit eb779038de59e028ebbd6533072acec7b5fc98af Author: ouz-a Date: Thu Sep 28 19:51:49 2023 +0300 simplify visit commit 0cca109473161c5c71de53d8ea0c9b7ff0a9b5c4 Author: ouz-a Date: Thu Sep 28 19:46:39 2023 +0300 visit and fold ty::ref commit 8c41cd0d78caed65ebd2f057d5209fc564f9cc10 Author: ouz-a Date: Thu Sep 28 19:43:28 2023 +0300 simplify fold commit 9f2e15d2328df0d32c5515c7b9a922b810403982 Author: ouz-a Date: Thu Sep 28 19:21:12 2023 +0300 change visit to fold for ty and reg commit 809cd20618cce8fe9b128a35980d51cb458570d2 Author: Oli Scherer Date: Wed Sep 27 11:23:39 2023 +0000 Skip reinterning if nothing changed commit 0031cf7c7e5bd255a504df19f44cc0eaf240fd57 Author: Oli Scherer Date: Wed Sep 27 11:35:09 2023 +0000 Add a mir validation check to prevent OpaqueCast after analysis passes finish commit 17d7821a2a682d482c5403c61c1d22d8db5a438a Author: Oli Scherer Date: Wed Sep 27 11:20:17 2023 +0000 Strip `OpaqueCast` during `RevealAll`. commit 2d4201f7c65b223967bb12aed2a790f85e457969 Author: Oli Scherer Date: Wed Sep 27 11:23:39 2023 +0000 Skip reinterning if nothing changed commit 6ea2db7c2d78182fabf66a8c6ffc856446e1cf81 Author: Oli Scherer Date: Wed Sep 27 11:20:17 2023 +0000 Strip `OpaqueCast` during `RevealAll`. commit 479fa4a74d74b69c9bc5fc330519a92590f170e4 Author: Oli Scherer Date: Wed Sep 27 10:31:53 2023 +0000 Bless mir-opt tests commit 9a40f1aa131e39b01981cd4f276a38a85205caad Author: Oli Scherer Date: Mon Sep 11 17:41:10 2023 +0000 Remove unnecessary generator-check, which also fixes the issue within async functions commit f5df26dbecf39dccd0833a3a82eb1aea3d127e17 Author: Oli Scherer Date: Mon Sep 11 15:00:46 2023 +0000 Unconditionally run `RevealAll` pass and run it earlier commit ec6f554536b1d3ef0185f93b2b7273a40760c6f6 Author: Oli Scherer Date: Mon Sep 11 14:24:55 2023 +0000 Some tracing cleanups commit 25648de28f10799fa6274f64fa12475292231c72 Author: Federico Stra Date: Thu Sep 28 17:43:01 2023 +0200 isqrt: disable long running tests in Miri commit 925f8441645193c95bd870be0dd9d0b3d03a3020 Merge: dd91aba2fdd ff958ae3e4d Author: bors Date: Thu Sep 28 15:24:06 2023 +0000 Auto merge of #116230 - matthiaskrgr:rollup-hi1ciwy, r=matthiaskrgr Rollup of 3 pull requests Successful merges: - #116191 (Add regression test for rust-lang#56098) - #116214 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names) - #116221 (core/slice: Fix inconsistency between docs for `rotate_left` and `rotate_right`) r? `@ghost` `@rustbot` modify labels: rollup commit e0f4ab84a7e27e6449252ed416ceeb2fbb0fbbbe Author: Ralf Jung Date: Thu Sep 28 16:42:07 2023 +0200 update lockfile commit 6ef11ddc3bdf4b42c715450d2d8e163e39561c32 Merge: e0f4ab84a7e 377730efe4a Author: bors Date: Thu Sep 28 14:40:54 2023 +0000 Auto merge of #3092 - RalfJung:ui-test, r=RalfJung update ui_test In particular this includes https://github.com/oli-obk/ui_test/pull/167 :) commit 377730efe4ab8c4bca6c4d6058bcd413c9e67dfa Author: Ralf Jung Date: Thu Sep 28 16:34:07 2023 +0200 update ui_test commit ff958ae3e4d56ad2bb76479648e0ccb7022f9f95 Merge: efc938312c0 5e26e8c5bdd Author: Matthias Krüger Date: Thu Sep 28 15:58:44 2023 +0200 Rollup merge of #116221 - ArchUsr64:patch-1, r=ChrisDenton core/slice: Fix inconsistency between docs for `rotate_left` and `rotate_right` A minor fix for documentation inconsistency as shown below: ## Before: ![2023_09_28_0k3_Kleki](https://github.com/rust-lang/rust/assets/83179501/569a49d3-0d72-49ac-92a2-ef5e1d94130b) ## After: ![image](https://github.com/rust-lang/rust/assets/83179501/afd0c8d7-6fb7-4878-801b-b47c8fe23c7d) Docs url: https://doc.rust-lang.org/stable/core/primitive.slice.html#method.rotate_left commit efc938312c0265e82fb155529101f8a8e5fa5c45 Merge: ba0d97797a3 0487237f124 Author: Matthias Krüger Date: Thu Sep 28 15:58:44 2023 +0200 Rollup merge of #116214 - notriddle:master, r=aDotInTheVoid rustdoc: rename `issue-\d+.rs` tests to have meaningful names commit ba0d97797a30cafde9c5cf2aa9b0a165c11c5ba3 Merge: c01d8d238c5 ac9707d25cb Author: Matthias Krüger Date: Thu Sep 28 15:58:43 2023 +0200 Rollup merge of #116191 - apekros:issue-56098, r=petrochenkov Add regression test for rust-lang#56098 Closes #56098 commit d18d01a8b1d2a204c3b901f0bbf3412fe1cc7957 Merge: 29ed6fa1194 b413bf6c4ee Author: bors Date: Thu Sep 28 13:40:05 2023 +0000 Auto merge of #11576 - koka831:fix/10128, r=llogiq write_literal: Fix index of the remaining positional arguments - fixes https://github.com/rust-lang/rust-clippy/issues/10128 - `clippy --fix` replaces multiple warnings at once e.g.) ```rust writeln!(v, "{0} {1}", "hello", "world"); // before: `writeln!(v, "hello {1}", "world");` // now: `writeln!(v, "hello world");` ``` changelog: [`print_literal`], [`write_literal`]: Now handles positional argument properly commit dd91aba2fdd8e3b6d9248a401bd6eb2f8d445cdf Merge: c01d8d238c5 e7908608d9d Author: bors Date: Thu Sep 28 13:35:36 2023 +0000 Auto merge of #114882 - ChrisDenton:riddle-me, r=dtolnay Update windows ffi bindings Bump `windows-bindgen` to version 0.51.1. This brings with it some changes to the generated FFI bindings, but little that affects the code. One change that does have more of an impact is `SOCKET` being `usize` instead of either `u64` or `u32` (as is used in std's public `SOCKET` type). However, it's now easy enough to abstract over that difference. Finally I added a few new bindings that are likely to be used in pending PRs, mostly to make sure they're ok with the new metadata. r? libs commit 66bc682caba7d7c2ea68764e885b337e7610362e Author: Jason Newcomb Date: Wed Sep 27 11:01:41 2023 -0400 Fix `noop_method_call` detection for new diagnostic items commit fcdfd5b0b9efcf7797b0f1bf7e7ed47ff99de198 Author: Federico Stra Date: Thu Sep 28 13:59:19 2023 +0200 isqrt: `assume` that `isqrt` takes half as many bits https://github.com/rust-lang/rust/issues/89273#issuecomment-970581089 commit cfb819fa7e7dd16e756eca6d19ac78c7635436bd Author: bohan Date: Thu Sep 28 19:47:58 2023 +0800 resolve: skip underscore character during candidate lookup commit c01d8d238c57f9847e1f1dd5a1d2659b85e2a468 Merge: e2d6aa77ed3 6acb415e7c7 Author: bors Date: Thu Sep 28 11:47:54 2023 +0000 Auto merge of #114428 - ChaiTRex:master, r=dtolnay Convert `Into for ExitStatusError` to `From for ExitStatus` in `std::process` Implementing suggestion from https://github.com/rust-lang/rust/issues/84908#issuecomment-912352902: > I believe the impl on ExitStatusError should be > > ```rust > impl From for ExitStatus > ``` > > rather than > > ```rust > impl Into for ExitStatusError > ``` > > (there is generally never anything implemented as `Into` first, because implementing `From` reflexively provides `Into`) commit b325e9c60df758f1f1538c93e44b120a8fbf6d63 Author: Nikita Popov Date: Thu Sep 28 13:41:02 2023 +0200 Update LLVM submodule commit 29ed6fa11945d4333acd8eb72c8ee24f847ac8c7 Merge: 124f1b06596 1c77b0b2677 Author: bors Date: Thu Sep 28 10:34:33 2023 +0000 Auto merge of #11415 - Alexendoo:needless-raw-string-hashes-pedantic, r=flip1995 Move `needless_raw_string_hashes` to `pedantic` IMO it doesn't improve code enough to be warn by default. [It seems to be unclear to some also](https://github.com/rust-lang/rust-clippy/issues/11402), but that can probably be remedied separately changelog: Moved [`needless_raw_string_hashes`] to `pedantic` (Now allow-by-default) [#11415](https://github.com/rust-lang/rust-clippy/pull/11415) r? `@flip1995` commit 77f9eae9956f6c7c23bdf81c2efdd47625382ea2 Author: Federico Stra Date: Thu Sep 28 12:32:58 2023 +0200 fixup! isqrt: fix stability commit 51463175a46599eb69375861bfe3626f68d643a4 Author: Federico Stra Date: Thu Sep 28 12:12:18 2023 +0200 isqrt: cite source and rename variables to match original C code commit e2d6aa77ed3fdb2ec6ceb4ee05429457768a4c0f Merge: 6e09cff6d74 9bdf9e754e8 Author: bors Date: Thu Sep 28 09:59:03 2023 +0000 Auto merge of #98704 - vthib:impl-from-raw-for-childstd-structs, r=dtolnay Implement From for ChildStdin/out/err object ## Summary Comments in `library/std/src/process.rs` ( https://github.com/rust-lang/rust/commit/ab08639e5950f5c8a42a2870c9636181308c3686 ) indicates that `ChildStdin`, `ChildStdout`, `ChildStderr` implements some traits that are not actually implemented: `FromRawFd`, `FromRawHandle`, and the `From/From` from the io_safety feature. In this PR I implement `FromRawHandle` and `FromRawFd` for those 3 objects. ## Usecase I have a usecase where those implementations are basically needed. I want to customize in the `Command::spawn` API how the pipes for the parent/child communications are created (mainly to strengthen the security attributes on them). I can properly setup the pipes, and the "child" handles can be provided to `Child::spawn` easily using `Stdio::from_raw_handle`. However, there is no way to generate the `ChildStd*` objects from the raw handle of the created name pipe, which would be very useful to still expose the same API than in other OS (basically a `spawn(...) -> (Child, ChildStdin, ChildStdout, ChildSterr)`, where on windows this is customized), and to for example use `tokio::ChildStdin::from_std` afterwards. ## Questions * Are those impls OK to add? I have searched to see if those impls were missing on purpose, or if it was just never implemented because never needed. I haven't found any indication on why they couldn't be added, although the user clearly has to be very careful that the handle provided makes sense (i think, mainly that it is in overlapped mode for windows). * If this change is ok, adding the impls for the io_safety feature would probably be best, or should it be done in another PR? * I just copy-pasted the `#[stable(...)]` attributes, but the `since` value has to be updated, I'm not sure to which value. commit fed72e06644db562c043f2f9cec99f2b2d9cba9d Author: ouz-a Date: Thu Sep 28 12:47:21 2023 +0300 add visitor for Region commit c97ab231415aa46cd1d35e8d00d601dec0d23e86 Author: Federico Stra Date: Thu Sep 28 11:15:43 2023 +0200 isqrt: fix stability commit 17dfb18bd1ad15ce4437bb44ba30b0c82aad3e07 Author: Federico Stra Date: Thu Sep 28 10:43:41 2023 +0200 fixup! isqrt: initial implementation Fix C-ism and type inference. commit bb17fe8bf5b32cd7fefbab95b6b1b7ee04628dbd Author: ouz-a Date: Thu Sep 28 12:32:15 2023 +0300 add real folder to Region commit be50413ef00fde789e185352e3f8bf109d0f2a99 Author: Jakub Beránek Date: Thu Sep 28 10:18:20 2023 +0200 Add integration for new bors commit da2f897e590be03eb4acddfd9df804545b738b65 Author: ouz-a Date: Thu Sep 28 11:43:21 2023 +0300 remove un-needed variants commit 2069e8c218fcc8428ae400fe91b245c977859036 Author: ouz-a Date: Thu Sep 28 11:36:53 2023 +0300 fix imports commit b413bf6c4ee671df153b930dc2ba5b159c652c1d Author: koka Date: Thu Sep 28 17:12:00 2023 +0900 Fix index of the remaining positional arguments commit d83559939cf89f717d1fcd8266c5f457df6e37dd Author: ouz-a Date: Thu Sep 21 12:18:10 2023 +0300 make reg public and add visit, fold commit 5dc2214884483496ef8cf4a8fa7f1be189669974 Author: ouz-a Date: Thu Sep 21 12:12:06 2023 +0300 add stable for RegionKind commit e49aa04000b3443a8cf1650ee0a75d48ddf115d0 Author: ouz-a Date: Thu Sep 21 12:01:30 2023 +0300 add RegionDef commit 02b01a46de62d26a2769b7546481a6ab08da82b8 Author: ouz-a Date: Thu Sep 21 11:52:06 2023 +0300 make region struct and add neccesasry types commit 6e09cff6d74f19cab171586c8612f03110c33ebd Merge: 46da927abb3 86d5939abaf Author: bors Date: Thu Sep 28 08:05:39 2023 +0000 Auto merge of #116222 - matthiaskrgr:rollup-dnag90q, r=matthiaskrgr Rollup of 6 pull requests Successful merges: - #112959 (Change the wording in `std::fmt::Write::write_str`) - #115535 (format doc-comment code examples in std::process) - #115888 (fix a comment about assert_receiver_is_total_eq) - #116211 (more clippy complextity fixes ) - #116213 (Document -Zlink-native-libraries) - #116215 (Tweak wording of missing angle backets in qualified path) r? `@ghost` `@rustbot` modify labels: rollup commit bb5344a1bff6df6c1d5a932c1c5727d7f72a2f55 Author: Nicholas Nethercote Date: Wed Sep 20 08:04:14 2023 +1000 Inline and remove `DroplessArena::alloc_raw_without_grow`. It has a single call site. I find the code clearer with it gone. commit 55a1a5223a0930df1cf98c0ea759d15700da9e5d Author: Nicholas Nethercote Date: Wed Sep 20 07:54:27 2023 +1000 Reduce `grow_and_alloc_raw` to a single call site. The current structure is clumsy, calling `alloc_raw_without_grow` in one function, and then if that fails, calling another function that calls `alloc_raw_without_grow` again. commit 86d5939abafaadd63dd63a52fcd6a464f14c4188 Merge: be51067b4a1 3848ffcee7a Author: Matthias Krüger Date: Thu Sep 28 09:14:07 2023 +0200 Rollup merge of #116215 - estebank:parse-type-angle-bracket-tweak, r=compiler-errors Tweak wording of missing angle backets in qualified path commit be51067b4a132075630c8823c746868116a103f3 Merge: fa5b2fe2f54 f4ed73119ae Author: Matthias Krüger Date: Thu Sep 28 09:14:07 2023 +0200 Rollup merge of #116213 - tmandry:doclnl, r=ehuss Document -Zlink-native-libraries Originally added in #70095. commit fa5b2fe2f5470e35e1c44f23f934b5592e7ceedd Merge: 698448c0cd7 e8a33847fd1 Author: Matthias Krüger Date: Thu Sep 28 09:14:06 2023 +0200 Rollup merge of #116211 - matthiaskrgr:clippy3, r=compiler-errors more clippy complextity fixes redundant_guards, useless_format, clone_on_copy commit 698448c0cd7b34594099202156ed2f7670afd6de Merge: 0e338d7e23b d49123ddc9c Author: Matthias Krüger Date: Thu Sep 28 09:14:06 2023 +0200 Rollup merge of #115888 - RalfJung:assert_receiver_is_total_eq, r=dtolnay fix a comment about assert_receiver_is_total_eq "a type implements #[deriving]" doesn't make any sense, so I assume they meant "implement `Eq`"? Also the attribute is called `derive`. commit 0e338d7e23bd6029012b41af12746f8121074c7d Merge: 980fba73454 d8c1533252e Author: Matthias Krüger Date: Thu Sep 28 09:14:05 2023 +0200 Rollup merge of #115535 - tshepang:patch-2, r=dtolnay format doc-comment code examples in std::process commit 980fba7345473eb3e8fcf405cb992a8ce80332b3 Merge: aeaa5c30e5c e2f70324089 Author: Matthias Krüger Date: Thu Sep 28 09:14:05 2023 +0200 Rollup merge of #112959 - tbu-:pr_fmt_error_wording, r=dtolnay Change the wording in `std::fmt::Write::write_str` Refer to the error instead of expanding its name. commit 9bdf9e754e82cadfacdb081ef2b0a0fe8df9be25 Author: David Tolnay Date: Thu Sep 28 00:13:02 2023 -0700 Update stability attribute for child stream From impls commit 702da3b89c8c586fea9d257779e0e75562efa552 Author: Andre Bogus Date: Thu Sep 28 08:31:14 2023 +0200 stabilize `Option::as_`(`mut_`)`slice` commit 5e26e8c5bdd82c507f1ab4fdb29cad6f5861e4bd Author: Anshul <83179501+ArchUsr64@users.noreply.github.com> Date: Thu Sep 28 11:58:37 2023 +0530 changed 'rotate' to 'rotating' commit 46da927abb389f646d9b0c500e5c386aec61ecf9 Merge: aeaa5c30e5c b2d35e1f4bc Author: bors Date: Thu Sep 28 06:16:01 2023 +0000 Auto merge of #114041 - nvzqz:nvzqz/shared_from_array, r=dtolnay Implement `From<[T; N]>` for `Rc<[T]>` and `Arc<[T]>` Given that `Box<[T]>` already has this conversion, the shared counterparts should also have it. commit e2f70324089a2eb75d52552c058170e37d0064f0 Author: David Tolnay Date: Wed Sep 27 22:55:34 2023 -0700 Fix "unresolved link to std::fmt::Error" error: unresolved link to `std::fmt::Error` --> library/core/src/fmt/mod.rs:115:52 | 115 | /// This function will return an instance of [`std::fmt::Error`] on error. | | = note: `-D rustdoc::broken-intra-doc-links` implied by `-D warnings` commit 25407bc0bb2fd4aa2c1a37c81a72084160d097fd Author: Nicholas Nethercote Date: Wed Sep 20 07:51:24 2023 +1000 Make `DroplessArena::alloc` call `DroplessArena::alloc_raw`. They're very similar. commit 98d97b7323a55fce821bab6606bf216dbb97523a Author: Nicholas Nethercote Date: Wed Sep 20 07:45:46 2023 +1000 Use `Layout::new` consistently in `DroplessArena::alloc`. commit 51edc219906f0973dd66b4b6ff5ff0ac857a4cc6 Author: Nicholas Nethercote Date: Wed Sep 20 07:36:19 2023 +1000 Remove `unsafe` from `TypedArena::alloc_raw_slice`. There's no good reason for it. commit 55de23ed5dff82a300cf379c9c756f82df48a987 Author: Nicholas Nethercote Date: Wed Sep 20 07:32:12 2023 +1000 Inline and remove `TypedArena::ensure_capacity`. It has a single callsite. commit 0001eddb933ff9e5beeb8dd00c507b7abbd85e94 Author: Nicholas Nethercote Date: Wed Sep 20 07:23:42 2023 +1000 Inline and remove `DroplessArena::grow_and_alloc`. It has a single callsite. commit a11f7e4c0f39c4665ec3b6c03b59fc9c9b7251a2 Author: Nicholas Nethercote Date: Wed Sep 20 08:51:38 2023 +1000 Remove some unnecessary lifetimes. commit 79b11f0802a17f5fce65e22b4934104d40a10e93 Author: Nicholas Nethercote Date: Tue Sep 19 17:08:13 2023 +1000 rustc_arena: tweak some comments. commit 024279a2e931c0bc68b235fd683ebcefc3fc718b Merge: 1a3dd7ea7d9 f2623ac49b3 Author: bors Date: Thu Sep 28 05:42:54 2023 +0000 Auto merge of #3089 - rust-lang:rustup-2023-09-28, r=RalfJung Automatic sync from rustc commit f2623ac49b3dbcee5a0828c035157ca92bd0db2c Merge: 3b091cb5044 2ba4eb2d49e Author: The Miri Conjob Bot Date: Thu Sep 28 05:19:36 2023 +0000 Merge from rustc commit 3b091cb5044ecc956a87993870276311a0e15340 Author: The Miri Conjob Bot Date: Thu Sep 28 05:11:51 2023 +0000 Preparing for merge from rustc commit aeaa5c30e5c9041264a2e8314b68ad84c2dc3169 Merge: 2ba4eb2d49e 27e10e2b5e2 Author: bors Date: Thu Sep 28 04:26:40 2023 +0000 Auto merge of #111278 - EFanZh:implement-from-array-refs-for-vec, r=dtolnay Implement `From<{&,&mut} [T; N]>` for `Vec` where `T: Clone` Currently, if `T` implements `Clone`, we can create a `Vec` from an `&[T]` or an `&mut [T]`, can we also support creating a `Vec` from an `&[T; N]` or an `&mut [T; N]`? Also, do I need to add `#[inline]` to the implementation? ACP: rust-lang/libs-team#220. [Accepted] Closes #100880. commit 2ba4eb2d49e774b5fbc2a06258ac7b0f60b92b7e Merge: b9dd2ce4081 809ab64e97f Author: bors Date: Thu Sep 28 02:34:16 2023 +0000 Auto merge of #116208 - matthiaskrgr:the_loop_that_wasnt, r=GuillaumeGomez rustdoc: while -> if we will always return once we step inside the while-loop thus `if` is sufficient here commit f99fdac3df5f97287857786bcce9660250009cbf Author: WANG Rui Date: Thu Sep 28 10:09:53 2023 +0800 ci: upgrade to crosstool-ng 1.26.0 commit b9dd2ce4081be0698bf7759f85e2314508b5c56a Merge: fbd4423b970 17b1026448e Author: bors Date: Thu Sep 28 00:44:08 2023 +0000 Auto merge of #116204 - Alexendoo:rustc-lint-macro-paths, r=cjgillot Use absolute paths in rustc_lint::passes macros A cosmetic change, so the callsite doesn't have to import things. Makes nicer for us to try in clippy commit 124f1b06596ff1749d5b5da59e32d1c229421219 Merge: 4494b6947f1 62b8ef304ad Author: bors Date: Thu Sep 28 00:41:36 2023 +0000 Auto merge of #11574 - unexge:missing-assert-message-docs, r=Alexendoo Mention that `missing_assert_message` lint ignores test functions Updates `missing_assert_message`'s docs to reflect that it ignores test functions as pointed out by `@mickvangelderen` in https://github.com/rust-lang/rust-clippy/pull/10362#issuecomment-1732288652 --- changelog: [`missing_assert_message`]: Update docs to reflect this lint ignores test functions commit 3848ffcee7ae74e15e4b68ad0f45a29f1fc170c7 Author: Esteban Küber Date: Thu Sep 28 00:37:20 2023 +0000 Tweak wording of missing angle backets in qualified path commit 0487237f1247d2395c50e52640ef547b88fd38be Author: Michael Howell Date: Wed Sep 27 17:22:18 2023 -0700 rustdoc: add URLs for test issues commit f4ed73119ae6b9af4b6722954265ed617d066d2e Author: Tyler Mandry Date: Wed Sep 27 17:12:40 2023 -0700 Document -Zlink-native-libraries Originally added in #70095. commit 7cd8b2c9253e83c8101a45ccf6e401cd3160650c Author: Michael Howell Date: Wed Sep 27 17:15:37 2023 -0700 Rename issue-\d+.rs tests to have meaningful names commit 79195d5cbbf839ed6db8cda394b0a7b2ef447ba7 Author: Michael Howell Date: Wed Sep 27 16:51:21 2023 -0700 Add `crate_name` to test so that it can be renamed commit fbd4423b9709dd810fc1d8f609ef9d123c6207d6 Merge: e7c502d9309 2eb17581ac0 Author: bors Date: Wed Sep 27 22:56:40 2023 +0000 Auto merge of #116148 - DaniPopes:rustdoc-type-layout-ws, r=jsha Fix whitespace in rustdoc type_layout.html `Size: ` was missing a space after the colon: ![image](https://github.com/rust-lang/rust/assets/57450786/c5a672f3-a28a-4b56-91e7-a4e6ffc8106e) commit e8a33847fd1d92a50d53287c737670d1a8f80df0 Author: Matthias Krüger Date: Thu Sep 28 00:20:32 2023 +0200 don't clone copy types commit fd95627134e85f56f2e162790f56943b407f1a34 Author: Matthias Krüger Date: Wed Sep 27 23:48:47 2023 +0200 fix clippy::{redundant_guards, useless_format} commit e7c502d9309ae6bc6a9750514ba7fe397844e84c Merge: 7b4b1b08b6d 901be42bc09 Author: bors Date: Wed Sep 27 21:06:30 2023 +0000 Auto merge of #109597 - cjgillot:gvn, r=oli-obk Implement a global value numbering MIR optimization The aim of this pass is to avoid repeated computations by reusing past assignments. It is based on an analysis of SSA locals, in order to perform a restricted form of common subexpression elimination. By opportunity, this pass allows for some simplifications by combining assignments. For instance, this pass could be able to see through projections of aggregates to directly reuse the aggregate field (not in this PR). We handle references by assigning a different "provenance" index to each `Ref`/`AddressOf` rvalue. This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we consider all the derefs of an immutable reference to a freeze type to give the same value: ```rust _a = *_b // _b is &Freeze _c = *_b // replaced by _c = _a ``` commit 62b8ef304adf92e2f5d3d8f172fa1e4661183692 Author: unexge Date: Wed Sep 27 22:06:01 2023 +0100 Mention that `missing_assert_message` lint ignores test functions commit 809ab64e97fc7d7f0f74d2ba13811ce657a740e3 Author: Matthias Krüger Date: Wed Sep 27 22:07:33 2023 +0200 rustdoc: while -> if we will always return once we step inside the while-loop thus `if` is sufficient here commit 7b4b1b08b6d4c68a2c7dcb49c312f9fc59d8db86 Merge: d4589a492f5 2ff14b00501 Author: bors Date: Wed Sep 27 19:17:30 2023 +0000 Auto merge of #114901 - compiler-errors:style-guide-wc, r=calebcartwright Amend style guide section for formatting where clauses in type aliases This PR has two parts: 1. Amend wording about breaking before or after the `=`, which is a style guide bugfix to align it with current rustfmt behavior. 2. Explain how to format trailing (#89122) where clauses, which are preferred in both GATs (#90076) and type aliases (#114662). r? `@joshtriplett` commit 1b2c1a85833ce2eb692054e0bbfe18c8911df216 Author: Urgau Date: Wed Sep 27 17:14:01 2023 +0200 Fix ICE by introducing an expr_or_init variant for outside bodies commit bd360472b13c3aaa642dd3d56945635612aaef73 Author: Urgau Date: Wed Sep 27 15:38:32 2023 +0200 Simplify casting logic of the invalid_reference_casting lint commit d4589a492f5419220c73d216dd538feb30b9b0c5 Merge: c4ce33cfbc8 08c4963a32a Author: bors Date: Wed Sep 27 16:09:54 2023 +0000 Auto merge of #116202 - emmanuel-ferdman:wip, r=ehuss Update location of `personality/gcc.rs` **PR Summary**: PR updates the location of `personality/gcc.rs` file in the docs. commit 08c4963a32a4a9e9d9ce4d76e53a7d4bb85b1711 Author: Emmanuel Ferdman Date: Wed Sep 27 18:30:33 2023 +0300 Update location of personality commit 17b1026448e9225fed38a0816a8e5a2b6a82c3c1 Author: Alex Macleod Date: Wed Sep 27 15:06:59 2023 +0000 Use absolute paths in rustc_lint::passes macros A cosmetic change, so the callsite doesn't have to import things commit c4ce33cfbc800ed027f4ebd7d2033fcb4d6c6665 Merge: 92009f217a0 12a1b55afdf Author: bors Date: Wed Sep 27 13:20:53 2023 +0000 Auto merge of #115887 - RalfJung:pat, r=oli-obk thir::pattern: update some comments and error type names Follow-up to [these comments](https://github.com/rust-lang/rust/pull/105750#pullrequestreview-1629697578). Please carefully fact-check, I'm new to this area of the compiler! commit e577dcdd4dd01c65921815cb9253a2fb96979a99 Author: Urgau Date: Sun Sep 17 16:24:22 2023 +0200 Prefer expr_or_init over manual init detection commit 92009f217a05d12716e278b4ade8d2624946eb5f Merge: 085acd02d4a ab8307331af Author: bors Date: Wed Sep 27 11:28:36 2023 +0000 Auto merge of #116093 - RalfJung:link_llvm_intrinsics, r=oli-obk make link_llvm_intrinsics and platform_intrinsics features internal These are both a lot like `feature(intrinsics)`, just slightly different syntax, so IMO it should be treated the same (also in terms of: if you get ICEs with this feature, that's on you -- we are not doing "nice" type-checking for intrinsics). commit 085acd02d4abaf2ccaf629134caa83cfe23283c8 Merge: 376f3f05905 a6f066596b9 Author: bors Date: Wed Sep 27 08:45:44 2023 +0000 Auto merge of #116193 - matthiaskrgr:rollup-wpt7m5t, r=matthiaskrgr Rollup of 4 pull requests Successful merges: - #115934 (Split out the stable part of smir into its own crate to prevent accidental usage of forever unstable things) - #116149 (Anonymize binders for `refining_impl_trait` check) - #116178 (Add test for `const async fn`) - #116187 (Add context to `let: Ty = loop { break };`) r? `@ghost` `@rustbot` modify labels: rollup commit a6f066596b9802ba5c9859c962c79fc50e26367f Merge: 243ce35b9fb 4b15959218a Author: Matthias Krüger Date: Wed Sep 27 10:42:35 2023 +0200 Rollup merge of #116187 - estebank:small-tweak, r=compiler-errors Add context to `let: Ty = loop { break };` We weren't accounting for the case where `break` was immediately within the `loop` block. commit 243ce35b9fbad1fb024c85a96ef79ef9755935af Merge: 50417a54573 35f9345076b Author: Matthias Krüger Date: Wed Sep 27 10:42:35 2023 +0200 Rollup merge of #116178 - Milo123459:milo/add-test-for-const-async-function-in-main, r=wesleywiser Add test for `const async fn` This adds a test for #102796 commit 50417a5457327e0eb6cd214307421c798cef990b Merge: d4858878c19 305524d1d65 Author: Matthias Krüger Date: Wed Sep 27 10:42:34 2023 +0200 Rollup merge of #116149 - compiler-errors:anonymize, r=lcnr Anonymize binders for `refining_impl_trait` check We're naively using the equality impl for `ty::Clause` in the refinement check, which is okay *except* for binders, which carry some information about where they come from in the AST. Those locations are not gonna be equal between traits and impls, so anonymize those clauses so that this doesn't matter. Fixes #116135 commit d4858878c192dee3ae74aec7244f725426f6ab84 Merge: 376f3f05905 411e431c707 Author: Matthias Krüger Date: Wed Sep 27 10:42:34 2023 +0200 Rollup merge of #115934 - oli-obk:smir_identity, r=spastorino Split out the stable part of smir into its own crate to prevent accidental usage of forever unstable things Some groundwork for being able to work on https://github.com/rust-lang/project-stable-mir/issues/27 at all r? `@spastorino` commit ac9707d25cb05b43a4466dbf18ca56f1b463ea78 Author: apekros Date: Wed Sep 27 18:05:14 2023 +1000 Add regression test for rust-lang#56098 commit 1a3dd7ea7d929db798b7095d3c25f50b49a52fb4 Merge: e86c68aa545 c8a44b1eaf5 Author: bors Date: Wed Sep 27 06:51:43 2023 +0000 Auto merge of #3087 - rust-lang:rustup-2023-09-27, r=RalfJung Automatic sync from rustc commit c8a44b1eaf5aed5cf8e57340f1ac56c9bad08acf Author: Ralf Jung Date: Wed Sep 27 08:50:16 2023 +0200 clippy commit b1f5c6683bb38da2cef8d1aa3fb3f88c357d4ae4 Merge: fc0d833f6fb 085acd02d4a Author: The Miri Conjob Bot Date: Wed Sep 27 05:48:00 2023 +0000 Merge from rustc commit fc0d833f6fb9876c367bb738927525102e5761a7 Author: The Miri Conjob Bot Date: Wed Sep 27 05:38:37 2023 +0000 Preparing for merge from rustc commit 376f3f059059b7fdd1331c77103943fd7c22918c Merge: d206f2c0857 64df5a851e1 Author: bors Date: Wed Sep 27 05:31:15 2023 +0000 Auto merge of #116166 - Zalathar:unreachable, r=cjgillot Skip MIR pass `UnreachablePropagation` when coverage is enabled When coverage instrumentation and MIR opts are both enabled, coverage relies on two assumptions: - MIR opts that would delete `StatementKind::Coverage` statements instead move them into bb0 and change them to `CoverageKind::Unreachable`. - MIR opts won't delete all `CoverageKind::Counter` statements from an instrumented function. Most MIR opts naturally satisfy the second assumption, because they won't remove coverage statements from bb0, but `UnreachablePropagation` can do so if it finds that bb0 is unreachable. If this happens, LLVM thinks the function isn't instrumented, and it vanishes from coverage reports. A proper solution won't be possible until after per-function coverage info lands in #116046, but for now we can avoid the problem by turning off this particular pass when coverage instrumentation is enabled. --- cc `@cjgillot` since I found this while investigating coverage problems encountered by #113970 `@rustbot` label +A-code-coverage +A-mir-opt commit d206f2c0857eb879877f27508139dd62a40294c3 Merge: 6b99cf1d35c 0ff1254d91d Author: bors Date: Wed Sep 27 03:41:23 2023 +0000 Auto merge of #116189 - weihanglo:update-cargo, r=weihanglo Update cargo 11 commits in 414d9e3a6d8096f3e276234ce220c868767a8792..e6aabe8b3fcf639be3a5bf68e77853bd7b3fa27d 2023-09-22 07:03:57 +0000 to 2023-09-26 16:31:53 +0000 - Use full target spec for `cargo rustc --print --target` (rust-lang/cargo#12743) - feat(embedded): Hack in code fence support (rust-lang/cargo#12681) - chore(ci): Update Renovate schema (rust-lang/cargo#12741) - more specific registry index not found msg (rust-lang/cargo#12732) - docs: warn about upload timeout (rust-lang/cargo#12733) - Fix some typos (rust-lang/cargo#12730) - upgrade gitoxide to v0.54 (rust-lang/cargo#12731) - Update target-arch-aware crates to support mips r6 targets (rust-lang/cargo#12720) - Buffer console status messages. (rust-lang/cargo#12727) - Fix spurious errors with networking tests. (rust-lang/cargo#12726) - refactor(SourceId): merge `name` and `alt_registry_key` into one enum (rust-lang/cargo#12675) r? ghost commit 3b75db7aa6692db31fdffd3c78d2a8029c536318 Merge: 7f132e8e3a7 55074827b52 Author: bors Date: Wed Sep 27 01:48:53 2023 +0000 Auto merge of #116163 - compiler-errors:lazyness, r=oli-obk Don't store lazyness in `DefKind::TyAlias` 1. Don't store lazyness of a type alias in its `DefKind`, but instead via a query. 2. This allows us to treat type aliases as lazy if `#[feature(lazy_type_alias)]` *OR* if the alias contains a TAIT, rather than having checks for both in separate parts of the codebase. r? `@oli-obk` cc `@fmease` commit 6b99cf1d35c8b7855a6b7f503d91edb223f027a1 Merge: e1636a0939f d6ce9ce115e Author: bors Date: Wed Sep 27 01:48:53 2023 +0000 Auto merge of #116163 - compiler-errors:lazyness, r=oli-obk Don't store lazyness in `DefKind::TyAlias` 1. Don't store lazyness of a type alias in its `DefKind`, but instead via a query. 2. This allows us to treat type aliases as lazy if `#[feature(lazy_type_alias)]` *OR* if the alias contains a TAIT, rather than having checks for both in separate parts of the codebase. r? `@oli-obk` cc `@fmease` commit 0ff1254d91d5b51a5079bd0729b41beb7a2f4adc Author: Weihang Lo Date: Wed Sep 27 09:21:34 2023 +0800 Update cargo New license exceptions from gix: * (byteyarn", "Apache-2.0") * ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause") commit e1636a0939fe8f7943d543f4cd0d7454ea4df487 Merge: 5ae769f06bb 17b313fb573 Author: bors Date: Wed Sep 27 00:03:53 2023 +0000 Auto merge of #116156 - oli-obk:opaque_place_unwrap, r=compiler-errors Only prevent field projections into opaque types, not types containing opaque types fixes https://github.com/rust-lang/rust/issues/115778 I did not think that original condition through properly... I'll also need to check the similar check around the other `ProjectionKind::OpaqueCast` creation site (this one is in hir, the other one is in mir), but I'll do that change in another PR that doesn't go into a beta backport. commit 4b15959218a4e856d95329d7752b1c55d5922de5 Author: Esteban Küber Date: Tue Sep 26 23:46:10 2023 +0000 Add context to `let: Ty = loop { break };` We weren't accounting for the case where `break` was immediately within the `loop` block. commit 7f132e8e3a7b8305cb22472d1bb5b14e18324e75 Merge: 772296c50e2 f2efdba6e2a Author: bors Date: Tue Sep 26 21:32:44 2023 +0000 Auto merge of #116144 - lcnr:subst-less, r=oli-obk subst -> instantiate continues #110793, there are still quite a few uses of `subst` and `substitute`, but changing them all in the same PR was a bit too much, so I've stopped here for now. commit 5ae769f06bbe2afc50cde219757a5915e61ba365 Merge: 5899a80ae60 3c52a3e280a Author: bors Date: Tue Sep 26 21:32:44 2023 +0000 Auto merge of #116144 - lcnr:subst-less, r=oli-obk subst -> instantiate continues #110793, there are still quite a few uses of `subst` and `substitute`, but changing them all in the same PR was a bit too much, so I've stopped here for now. commit 4494b6947f168f6b37e6e6077472b8c6ffe1f4b8 Merge: 493ab53f5ba 6cdff107782 Author: bors Date: Tue Sep 26 21:16:33 2023 +0000 Auto merge of #11569 - Alexendoo:needless-raw-string-descr, r=llogiq Describe the type of string in raw_strings lints changelog: none commit 35f9345076b80a26c7c96f18fb95f69adbee2375 Author: Milo <50248166+Milo123459@users.noreply.github.com> Date: Tue Sep 26 16:02:05 2023 +0000 add test fix tidy remove dir commit 5899a80ae60ec0959dcd4a7eca6eb02ce2866632 Merge: 6710e3312d5 ac0683b7831 Author: bors Date: Tue Sep 26 19:04:32 2023 +0000 Auto merge of #116102 - cjgillot:indirect-scalar, r=oli-obk Correct codegen of `ConstValue::Indirect` scalar and scalar pair This concerns 3 tricky cases with `ConstValue::Indirect`: - if we want a non-pointer scalar; - if we have non-zero offset; - if offset points to uninit memory => generate `poison` instead of an ICE. This case could happen in unreachable code, trying to extract a field from the wrong variant. Those cases are not currently emitted by the compiler, but are exercised by https://github.com/rust-lang/rust/pull/116012. commit 305524d1d655f744e739f45850bc6f74918ac0c9 Author: Michael Goulet Date: Mon Sep 25 15:00:38 2023 +0000 Anonymize binders for refining_impl_trait check commit 6710e3312d54f03f6462481199b9e72367a2568b Merge: 21627d60cfe 10928499676 Author: bors Date: Tue Sep 26 17:16:20 2023 +0000 Auto merge of #116154 - cjgillot:retain-cfg, r=oli-obk Use Vec::retain in remove_dead_blocks. r? `@ghost` commit cb55ce11dc86c288f3d0e2b7ada3db9364997893 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 26 16:52:08 2023 +0000 Fix potential crash on large constant ZST slice commit ca18301dfea63a041735aa146b74e61ab204180e Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 26 16:51:46 2023 +0000 Fix rustc test suite commit 901be42bc09bde57ad9b19a3c2c432fd3482279c Author: Camille GILLOT Date: Tue Sep 26 16:39:39 2023 +0000 Explicit simplify_place. commit 74e9f2657a86559f70997eefe0673369b332e094 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 26 16:35:18 2023 +0000 Rustup to rustc 1.74.0-nightly (0288f2e19 2023-09-25) commit 493ab53f5baf1fc6268277dd7f22a754b7af0177 Merge: 585b56f35f9 ec2f62677f5 Author: bors Date: Tue Sep 26 16:05:59 2023 +0000 Auto merge of #11556 - Alexendoo:manual-hash-one, r=Manishearth Add `manual_hash_one` lint Adds a lint to suggest using [`BuildHasher::hash_one`](https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one) changelog: [`manual_hash_one`]: new lint commit 21627d60cfe9867b64d3dc77aea1c79ad8d03265 Merge: 1f2bacf677c 6f4a0a1eb2d Author: bors Date: Tue Sep 26 15:27:19 2023 +0000 Auto merge of #116175 - matthiaskrgr:rollup-cwteiwy, r=matthiaskrgr Rollup of 5 pull requests Successful merges: - #116099 (Add regression test for issue #79865) - #116131 (Rename `cold_path` to `outline`) - #116151 (Fix typo in rustdoc unstable features doc) - #116153 (Update books) - #116162 (Gate and validate `#[rustc_safe_intrinsic]`) r? `@ghost` `@rustbot` modify labels: rollup commit b03d0b8512726b4903e3d26c8432130474892118 Merge: 8071ec78eac 1351de36eeb Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 26 15:12:11 2023 +0000 Sync from rust 0288f2e1955b154262e0669ec5f7bb9a4c6cf5aa commit 9b7f9c4328dde77396f815dc929de6cdbc700531 Author: Ralf Jung Date: Tue Sep 26 16:41:06 2023 +0200 take more clarifying text from Gankra's PR original source: https://github.com/rust-lang/rust/pull/95851 commit d49da0fe54251fbee190dc2adcdbffe787aecae7 Author: Federico Stra Date: Tue Sep 26 16:05:51 2023 +0200 isqrt: add more tests commit 6f4a0a1eb2dabc659fa216a04d7adcfb543adc14 Merge: 238a7b7981f f54db7c3a92 Author: Matthias Krüger Date: Tue Sep 26 15:57:26 2023 +0200 Rollup merge of #116162 - fmease:gate-n-validate-rustc_safe_intrinsic, r=Nilstrieb Gate and validate `#[rustc_safe_intrinsic]` Copied over from #116159: > This was added as ungated in https://github.com/rust-lang/rust/pull/100719/files#diff-09c366d3ad3ec9a42125253b610ca83cad6b156aa2a723f6c7e83eddef7b1e8fR502, probably because the author looked at the surrounding attributes, which are ungated because they are gated specially behind the staged_api feature. > > I don't think we need to crater this, the attribute is entirely useless without the intrinsics feature, which is already unstable.. r? ``@Nilstrieb`` commit 238a7b7981f48b4fb9d4168f88135040a95735eb Merge: c2e7a158de7 de377624be8 Author: Matthias Krüger Date: Tue Sep 26 15:57:26 2023 +0200 Rollup merge of #116153 - rustbot:docs-update, r=ehuss Update books ## rust-embedded/book 1 commits in 99ad2847b865e96d8ae7b333d3ee96963557e621..eac173690b8cc99094e1d88bd49dd61127fbd285 2023-09-12 07:34:44 UTC to 2023-09-12 07:34:44 UTC - USB connector-type correction (rust-embedded/book#360) ## rust-lang/nomicon 1 commits in e3f3af69dce71cd37a785bccb7e58449197d940c..ddfa4214487686e91b21aa29afb972c08a8f0d5b 2023-09-22 17:04:10 UTC to 2023-09-22 17:04:10 UTC - Fill "Beneath `std`" (rust-lang/nomicon#413) ## rust-lang/reference 1 commits in ee7c676fd6e287459cb407337652412c990686c0..5262e1c3b43a2c489df8f6717683a44c7a2260fd 2023-09-18 18:28:31 UTC to 2023-09-18 18:28:31 UTC - we reserve the right to reduce our amount of UB (rust-lang/reference#1397) ## rust-lang/rustc-dev-guide 8 commits in 08bb147d51e815b96e8db7ba4cf870f201c11ff8..a13b7c28ed705891c681ce5417b3d1cdb12cecd1 2023-09-25 05:14:41 UTC to 2023-09-11 21:29:18 UTC - Clarify all the `{AP,RP}IT{,IT}` impl trait types (rust-lang/rustc-dev-guide#1798) - Modify build instructions for optimized build (rust-lang/rustc-dev-guide#1795) - Remove outdated references to coverage debug code (rust-lang/rustc-dev-guide#1797) - Add deep dive document about early/late bound parameters interacting with turbofish (rust-lang/rustc-dev-guide#1794) - explain the MIR const vs TY const situation (rust-lang/rustc-dev-guide#1793) - fix type name (rust-lang/rustc-dev-guide#1792) - Clarify that `run-coverage` only runs in some of the CI jobs (rust-lang/rustc-dev-guide#1791) - Document the `coverage-map` and `run-coverage` test suites (rust-lang/rustc-dev-guide#1790) commit c2e7a158de76bfb94adfc59707e1df1b2e7efb0f Merge: 4eb72fdb15b 07e9d1cc246 Author: Matthias Krüger Date: Tue Sep 26 15:57:25 2023 +0200 Rollup merge of #116151 - DaniPopes:rustdoc-unstable-typo, r=fmease Fix typo in rustdoc unstable features doc commit 4eb72fdb15bd67175898642d5f243c2de6327762 Merge: b9caba610e8 2c507cae363 Author: Matthias Krüger Date: Tue Sep 26 15:57:25 2023 +0200 Rollup merge of #116131 - Zoxc:cold-path-rename, r=oli-obk Rename `cold_path` to `outline` I find this name to be a bit more descriptive. r? ``@oli-obk`` commit b9caba610e8808aa2a743a390eddf8d2f34befd0 Merge: 8bf0dec101d b6836849acf Author: Matthias Krüger Date: Tue Sep 26 15:57:24 2023 +0200 Rollup merge of #116099 - eduardosm:issue-79865-regression, r=oli-obk Add regression test for issue #79865 Closes https://github.com/rust-lang/rust/issues/79865 commit ec2f62677f5e7e6a1ed7e02fd61100c78c896d86 Author: Alex Macleod Date: Sat Sep 23 17:34:05 2023 +0000 Add `manual_hash_one` lint commit 68f0b475c76de88fb5cb37c8cd0163703354415a Author: Federico Stra Date: Tue Sep 26 15:44:28 2023 +0200 isqrt: remove duplication by delegating to unsigned integers commit 1f2bacf677c585761e05e41ebab6ebf3af4216f5 Merge: 8bf0dec101d a1d6fc43403 Author: bors Date: Tue Sep 26 13:38:28 2023 +0000 Auto merge of #115893 - RalfJung:match-require-partial-eq, r=oli-obk lint towards rejecting consts in patterns that do not implement PartialEq I think we definitely don't want to allow such consts, so even while the general plan around structural matching is up in the air, we can start the process of getting non-PartialEq matches out of the ecosystem. commit 6cdff107782be2c00ce37267bc5b2181dc1f12f7 Author: Alex Macleod Date: Tue Sep 26 11:40:10 2023 +0000 Describe the type of string in raw_strings lints commit a9030e668867dda6eb153f8b2518491b2c38d1d7 Author: Oli Scherer Date: Tue Sep 26 11:48:36 2023 +0000 Add tests for simd_shuffle{_generic} commit 8bf0dec101dc458a411401a826994006abd2f022 Merge: d23062b5be6 ba8d53dc8fd Author: bors Date: Tue Sep 26 10:34:57 2023 +0000 Auto merge of #116109 - Zoxc:no-dep-graph-thread, r=oli-obk Don't use a thread to load the dep graph This removes the use of a thread to load the dep graph. It's not currently useful as we immediately block on it. r? `@oli-obk` commit 64df5a851e1cb8c2ae539aa5331d48b8f3646bf4 Author: Zalathar Date: Mon Sep 25 23:09:27 2023 +1000 Skip MIR pass `UnreachablePropagation` when coverage is enabled When coverage instrumentation and MIR opts are both enabled, coverage relies on two assumptions: - MIR opts that would delete `StatementKind::Coverage` statements instead move them into bb0 and change them to `CoverageKind::Unreachable`. - MIR opts won't delete all `CoverageKind::Counter` statements from an instrumented function. Most MIR opts naturally satisfy the second assumption, because they won't remove coverage statements from bb0, but `UnreachablePropagation` can do so if it finds that bb0 is unreachable. If this happens, LLVM thinks the function isn't instrumented, and it vanishes from coverage reports. A proper solution won't be possible until after per-function coverage info lands in #116046, but for now we can avoid the problem by turning off this particular pass when coverage instrumentation is enabled. commit 585b56f35f92f7f0d081d87f1e3a6894ed1f64a2 Merge: bf4c9981798 fab90003b86 Author: bors Date: Tue Sep 26 08:46:51 2023 +0000 Auto merge of #10300 - koka831:fix/9942, r=xFrednet Do not lint when imported item contains underscore fix https://github.com/rust-lang/rust-clippy/issues/9942 changelog: [`wildcard_imports`]: No longer lints when imported items contain an item with the name `_` commit d185e0d899272030fd137f7adcf269e60c14901e Author: WANG Rui Date: Tue Aug 29 22:17:06 2023 +0800 Promote loongarch64-unknown-none* to Tier 2 MCP: https://github.com/rust-lang/compiler-team/issues/664 commit 159293cdbf9aaa32754af395dbb9833fe236a8a6 Author: lcnr Date: Mon Sep 25 15:46:38 2023 +0200 subst -> instantiate commit f2efdba6e2ab000d8210e8855fc0bcddbcf58b64 Author: lcnr Date: Mon Sep 25 15:46:38 2023 +0200 subst -> instantiate commit 3c52a3e280a5fd1e8e4b48a5ec349aa00dcd859c Author: lcnr Date: Mon Sep 25 15:46:38 2023 +0200 subst -> instantiate commit d23062b5be6bbf5be15226c7f497c89cf7d3d6e1 Merge: 27b4eb96d13 6d331b7f031 Author: bors Date: Tue Sep 26 07:20:55 2023 +0000 Auto merge of #116139 - flip1995:clippyup, r=Manishearth Clippy subtree update r? `@Manishearth` commit 27b4eb96d13106332d511be2ea6d0c008a57aa6e Merge: a6dce3bac50 ad509633a26 Author: bors Date: Tue Sep 26 05:33:55 2023 +0000 Auto merge of #116125 - RalfJung:const-param-ty-eq, r=compiler-errors ConstParamTy: require Eq as supertrait As discussed with `@BoxyUwu` [on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/.60ConstParamTy.60.20and.20.60Eq.60). We want to say that valtree equality on const generic params agrees with `==`, but that only makes sense if `==` actually exists, hence we should have an appropriate bound. Valtree equality is an equivalence relation, so such a type can always be `Eq` and not just `PartialEq`. commit fab90003b860409113b60b11b5c3c58547c3f0ad Author: koka Date: Mon Feb 6 21:09:39 2023 +0900 Do not lint when imported item contains underscore commit a6dce3bac50f14d6ef10f74b82c16e90bdb47d36 Merge: a61f6f3baa0 99a2fa17e68 Author: bors Date: Tue Sep 26 03:39:25 2023 +0000 Auto merge of #116124 - WaffleLapkin:fix-proc-macro-literal-to-string, r=compiler-errors Properly print cstr literals in `proc_macro::Literal::to_string` Previously we printed the contents of the string, rather than the actual string literal (e.g. `the c string` instead of `c"the c string"`). Fixes #112820 cc #105723 commit 55074827b52a2dd1551c19d8f42c59299877e59b Author: Michael Goulet Date: Tue Sep 26 02:15:32 2023 +0000 Don't store lazyness in DefKind commit d6ce9ce115e8d0859e378b411966905c8b815845 Author: Michael Goulet Date: Tue Sep 26 02:15:32 2023 +0000 Don't store lazyness in DefKind commit a61f6f3baa01fa52ddf6636f074ed7fe5c50aa7d Merge: c614c17626a 85681219963 Author: bors Date: Tue Sep 26 01:50:12 2023 +0000 Auto merge of #116072 - compiler-errors:rpitit-implied-bounds, r=aliemjay Use placeholders to prevent using inferred RPITIT types to imply their own well-formedness The issue here is that we use the same signature to do RPITIT inference as we do to compute implied bounds. To fix this, when gathering the assumed wf types for the method, we replace all of the infer vars (that will be eventually used to infer RPITIT types) with type placeholders, which imply nothing about lifetime bounds. This solution kind of sucks, but I'm not certain there's another feasible way to fix this. If anyone has a better solution, I'd be glad to hear it. My naive first solution was, instead of using placeholders, to replace the signature with the RPITIT projections that it originally started out with. But turns out that we can't just use the unnormalized signature of the trait method in `implied_outlives_bounds` since we normalize during WF computation -- that would cause a query cycle in `collect_return_position_impl_trait_in_trait_tys`. idk who to request review... r? `@lcnr` or `@aliemjay` i guess. Fixes #116060 commit bf4c9981798a319487e57af4214807dffc5fc778 Merge: 6c48ef3fc1a 1972cc89c4e Author: bors Date: Tue Sep 26 01:38:08 2023 +0000 Auto merge of #11564 - Alexendoo:config-test-test, r=giraffate Test that each config value exists in a test clippy.toml Inspired by #11560, adds a test that each config option exists in some form in a `clippy.toml` in `tests/` (currently some are in `ui-toml`, some in `ui-cargo`) changelog: none commit c614c17626a2dd02e88586a04bd0971d9ec2cae5 Merge: 0288f2e1955 ddb3b7e70a6 Author: bors Date: Tue Sep 26 00:03:45 2023 +0000 Auto merge of #116080 - estebank:issue-115905-2, r=compiler-errors Point at more causes of expectation of break value when possible Follow up to #116071. r? `@compiler-errors` Disregard the first commit, which is in the other PR. commit ddb3b7e70a6252a029059bbecfafd087d0415e63 Author: Esteban Küber Date: Mon Sep 25 22:10:08 2023 +0000 Use verbose suggestion for `break` without value commit 0288f2e1955b154262e0669ec5f7bb9a4c6cf5aa Merge: 6f13ea0d1a0 025a2cda0ec Author: bors Date: Mon Sep 25 22:04:53 2023 +0000 Auto merge of #116084 - fmease:rustdoc-fix-x-crate-async-fn, r=GuillaumeGomez rustdoc: correctly render the return type of cross-crate async fns Fixes #115760. commit 3747ef5d6f66525fd42d38b068fd81f163adb482 Author: Esteban Küber Date: Mon Sep 25 21:57:22 2023 +0000 Handle all arbitrary `loop` nesting in `break` type errors commit 2c507cae363a71f16069bbf602aa50e00f3ceec4 Author: John Kåre Alsaker Date: Mon Sep 25 03:27:25 2023 +0200 Rename `cold_path` to `outline` commit f54db7c3a927ec20dc0c20f9cd41b8e9be345bea Author: León Orell Valerian Liehr Date: Mon Sep 25 21:40:40 2023 +0200 Gate and validate #[rustc_safe_intrinsic] commit 6f13ea0d1a0687073d36b5b1f7dd0e41e67665fb Merge: 7bf47a47926 91544e6a937 Author: bors Date: Mon Sep 25 20:17:01 2023 +0000 Auto merge of #115704 - nebulark:s_object, r=nagisa Pass name of object file to LLVM so it can correctly emit S_OBJNAME in pdb files on Windows This should be the remaining fix to close https://github.com/rust-lang/rust/issues/96475 Setting ObjectFilenameForDebug in llvm::TargetOptions, so llvm it can emit S_OBJNAME in pdb files on Windows. Without a proper pdb parsing I am not able to add a unit test for this. The string is already appearing in the pdb file so I cannot just use grep. `@rustbot` label: +A-debuginfo commit 6c48ef3fc1a5ed259f1a12a80280702536dfdfbb Merge: 78ddc8d17db 39f7f695dab Author: bors Date: Mon Sep 25 19:48:31 2023 +0000 Auto merge of #11557 - Alexendoo:dev-new-lint-msrv-test, r=Manishearth Add msrv test template for `cargo dev new_lint --msrv` changelog: none commit ea026f93d696c321df3c4e397046ae72a2a9d283 Author: MaxHearnden Date: Mon Sep 25 20:22:20 2023 +0100 quote argument to sh -n This prevents glob expansion (*.py) and field splitting commit 7bf47a47926126a80b1a101b0b4b0e15eb7bed0d Merge: 1cbfeabfa9f 93863383c82 Author: bors Date: Mon Sep 25 18:29:26 2023 +0000 Auto merge of #116070 - eduardosm:IoSlice-advance_slices-checked_add, r=Mark-Simulacrum Avoid overflow in `IoSlice::advance_slices` Noticed in https://github.com/rust-lang/rust/issues/62726#issuecomment-1713997431. commit 58adfd84e29c268214928373ba61f8afbce75acf Author: Esteban Küber Date: Mon Sep 25 18:21:52 2023 +0000 Account for more cases of nested `loop`s for `break` type mismatches commit b0412d597e75d66ac5f07c642abae49c739d4fde Author: The 8472 Date: Mon Sep 25 19:54:26 2023 +0200 Document that Instant may or may not include system-suspend time commit 17b313fb5734df8186071d4e30e46673098bb6a9 Author: Oli Scherer Date: Mon Sep 25 17:40:37 2023 +0000 Only prevent field projections into opaque types, not types containing opaque types commit 91544e6a937b4c2c7181578533e6d10991559c14 Author: Florian Schmiderer Date: Sat Sep 9 14:00:24 2023 +0200 Pass name of object file to LLVM so it can correctly emit S_OBJNAME commit 109284996763bb778b07325386110ea5095cd82d Author: Camille GILLOT Date: Mon Sep 25 17:08:40 2023 +0000 Use Vec::retain in remove_dead_blocks. commit a1d6fc43403fadc5564af50d6212d45d9aace84d Author: Ralf Jung Date: Mon Sep 25 18:28:22 2023 +0200 rename lint; add tracking issue commit de377624be86c95374991fc7ac612daa9e81b2c7 Author: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon Sep 25 13:00:44 2023 -0400 Update books commit 1cbfeabfa9fb688cd5d2b8faf7ef2de8ab38dd9d Merge: 9d32ba3a721 a1d181d740d Author: bors Date: Mon Sep 25 16:32:34 2023 +0000 Auto merge of #113396 - lenko-d:dont_ICE_when_no_bound_vars_for_lifetime_binders, r=compiler-errors Don't ICE when no bound vars found while doing closure hir type check The problem was that we were not visiting the const generic default argument in a bound where predicate when the HIR gets traversed in hir_analysis -> collect -> resolve_bound_vars. Fixes [112574](https://github.com/rust-lang/rust/issues/112574) commit d00c7e78ea9e887e7e7d04dbe6c233444f4e6295 Author: Esteban Küber Date: Sat Sep 23 17:23:16 2023 +0000 Point at field definition when unresolved name exists in `Self` commit 81bca5f5cf2741c6f23c4e116ad3d38088701681 Author: Esteban Küber Date: Sat Sep 23 04:45:17 2023 +0000 When suggesting `self.x` for `S { x }`, use `S { x: self.x }` Tweak output. Fix #115992. commit 2e0ad2025fbae45f58149c321d2492a36808fea4 Author: Esteban Küber Date: Fri Sep 22 22:20:00 2023 +0000 Handle yet another case of `break` type mismatch commit f6d4950fee86c162ad0716b85b2c43111916c2ce Author: Esteban Küber Date: Fri Sep 22 22:17:12 2023 +0000 Point at previous breaks that have the expected type commit e86c68aa545fc3cfa5085811590e52011ed1a602 Merge: 32c0afb8804 ee30aaf7ea5 Author: bors Date: Mon Sep 25 15:48:48 2023 +0000 Auto merge of #3085 - RalfJung:test-norm, r=RalfJung fix normalization in backtrace-api tests also remove a normalization rule that doesn't seem to apply commit 07e9d1cc2467179c7d7e3a97142804256c15788f Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon Sep 25 17:38:39 2023 +0200 Fix typo in rustdoc unstable features doc commit 2eb17581ac05b3cab24fa2f96d9bf6f3ae17ad9b Author: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon Sep 25 17:04:51 2023 +0200 Fix whitespace in rustdoc type_layout.html commit 32c0afb8804cbb329eae3c82b68a4b8e71ebc054 Merge: b4dc4f3c1c5 5f440dd0696 Author: bors Date: Mon Sep 25 15:04:14 2023 +0000 Auto merge of #3083 - saethlin:gc-history, r=oli-obk GC the Stacked Borrows allocation history This handles the biggest contributor to https://github.com/rust-lang/miri/issues/3080 The benchmark that this adds demonstrates the memory improvement here, but our benchmark setup doesn't record memory usage, and `hyperfine` doesn't support emitting memory usage stats. I ran this benchmark manually with `/usr/bin/time -v cargo +miri miri run` :shrug: commit 411e431c7077cd875cb0ca89d1f61c4e5c55a795 Author: Oli Scherer Date: Mon Sep 25 15:02:10 2023 +0000 Rebase fallout commit 0f198579d0f65554e105e1d08dff66b491338376 Author: Ralf Jung Date: Mon Sep 25 16:59:46 2023 +0200 mir_to_const: fix handling of float arrays commit 9d32ba3a7219e28b0d44b5eb4d564ca58114356f Merge: af685931799 2ffef3949e4 Author: bors Date: Mon Sep 25 14:42:27 2023 +0000 Auto merge of #116147 - compiler-errors:jq, r=dtolnay Fix jq in CI r? `@Mark-Simulacrum` commit a38e98371bf2c2e81dd8f01da21330b87622dd3a Author: Oli Scherer Date: Thu Sep 14 15:50:11 2023 +0000 Split out the stable part of smir into its own crate to prevent accidental usage of forever unstable things commit 19f1d782d51d980ccb5c448e6a415188323b30ce Author: Oli Scherer Date: Mon Sep 18 14:47:39 2023 +0000 Move `Opaque` to `stable_mir` commit 33998a9751bf75e7e7b853038f09985855645949 Author: Oli Scherer Date: Mon Sep 18 11:02:26 2023 +0000 Fix test by adding a stable way to get an opaque DefKind commit 55b6f649024b372af901b3412a6d36c4284ccf3d Author: Oli Scherer Date: Thu Sep 14 15:43:30 2023 +0000 Eliminate escape hatch commit e02a139a23690bfd18dff8b8ec9c9b7161118507 Author: Oli Scherer Date: Thu Sep 14 15:42:28 2023 +0000 Eliminate `with_tables` helper commit 2ffef3949e4f04a1621ba47058bef6f78443abc4 Author: Michael Goulet Date: Mon Sep 25 14:30:26 2023 +0000 Fix jq in CI commit ce45221163717c60aaff33b2b1b7ce47ace9de87 Author: Ralf Jung Date: Mon Sep 25 16:23:47 2023 +0200 simply some valtree-to-const conversion commit 84d6894f2665bc2d3876538f4f2eb7e88d3b92ee Author: Ralf Jung Date: Mon Sep 25 16:19:02 2023 +0200 it's not Miri but MIR constants commit 025a2cda0ec511b6bc66f02dcddc408bf386e7ec Author: León Orell Valerian Liehr Date: Sat Sep 23 03:25:52 2023 +0200 rustdoc: correctly render ret ty of cross-crate async fns commit 221d0a661ae7579758de4586a8dc0496638d86ff Author: Milo <50248166+Milo123459@users.noreply.github.com> Date: Mon Sep 25 13:55:50 2023 +0000 update other place commit 7bda9b1255196a58798244374b366ebb99459545 Author: Milo <50248166+Milo123459@users.noreply.github.com> Date: Mon Sep 25 14:53:38 2023 +0100 clarify documentation about variable substituion commit ee30aaf7ea5ac3db40cd6da4172e214c5dbd9ef0 Author: Ralf Jung Date: Mon Sep 25 13:38:26 2023 +0200 fix normalization in backtrace-api tests also remove a normalization rule that doesn't seem to apply commit 4a64c796ee4d243566beff014016e12c165ef534 Author: Guillaume Gomez Date: Mon Sep 25 14:59:41 2023 +0200 Add test for enum variant value display commit a576dfd0c63508b7424dc1b59ad7f6b154341730 Author: Guillaume Gomez Date: Mon Sep 25 14:51:32 2023 +0200 Show enum variant value if it is a C-like variant commit 1972cc89c4e9db8f325137b58f7197aeef0a49d6 Author: Alex Macleod Date: Mon Sep 25 11:55:20 2023 +0000 Test that each config value exists in a test clippy.toml commit 78ddc8d17db66a41ed9c4970036edc69142b72fb Merge: 7671c283a50 6ad218ceef9 Author: bors Date: Mon Sep 25 11:35:33 2023 +0000 Auto merge of #11495 - blyxyas:help_message_reformat, r=flip1995 Add colored help to be consistent with Cargo On rust-lang/cargo#12578, a new colored help message format was introduced. This PR introduces the same styling from that `cargo help` message to our `cargo clippy --help` message. More information is provided in the original PR, fixes #11482. The perfect reviewing process would be that the reviewer installs this branch and checks for themselves, but here are some screenshots, there are some more screenshots in the original issue. ![image](https://github.com/rust-lang/rust-clippy/assets/73757586/0c4d1b6d-5aa2-4146-a401-9ae88f6dedf5) (Note that the actual text may change in the actual commit, that screenshot is just to test the colors). Also note that the `color-print` version **should always** be synced with Cargo's `color-print` version to avoid increasing build times in the rust-lang/rust repo. changelog:Add colors to the `cargo clippy --help` output :tada:. commit 6ad218ceef976d67af4bd065732b1f37595c882c Author: blyxyas Date: Wed Sep 13 19:43:11 2023 +0200 Add colored help commit b4dc4f3c1c53295476635c153e0055ab0166c2a0 Merge: efd04b6267f 71aea48fc6e Author: bors Date: Mon Sep 25 11:30:12 2023 +0000 Auto merge of #3008 - oli-obk:ui_test_progress_bars, r=RalfJung bump ui test crate The recommended way to run tests locally is `./miri bless -- -- --quiet`, which will show * progress bars * the currently running tests (allowing you to see which ones are still running towards the end of the test suite) * the output of the currently running tests (if they are slow). This means slow running tests can output lines to `stderr` and the last line will be shown after the test name and updated every few hundred milliseconds. As a side effect this PR also fixes #2998 and only builds dependencies if any tests actually need them (this means that with the next ui_test update we'll be able to merge all our test suites). Also fixes https://github.com/rust-lang/miri/issues/3052. commit 71aea48fc6e918922b069eb3346f54a33d9d7542 Author: Oli Scherer Date: Mon Sep 25 10:32:24 2023 +0000 Explain single element vector commit 1ec85a84413c527449ea1772b3f2c2f77b9be3d0 Author: Oli Scherer Date: Mon Sep 25 10:31:05 2023 +0000 Document new env var commit af685931799459879b2a8995524755a06ffb5eec Merge: 96ab09dbdd8 8e558bcf1ef Author: bors Date: Mon Sep 25 10:23:30 2023 +0000 Auto merge of #116029 - chenx97:mipsr6-update-crates, r=Mark-Simulacrum Update crates for better MIPS R6 support Update crates to remove dependency on old versions of rustix and linux-raw-sys. Update libc, rustix, and linux-raw-sys to enhance support for MIPS R6 introduced by #112374 Commands that do the update: ```shell cargo +nightly update tempfile clap cargo +nightly update linux-raw-sys rustix ``` commit 6d331b7f03164126f46094d8e9c14d4591e79918 Author: Philipp Krones Date: Mon Sep 25 11:29:11 2023 +0200 Update Cargo.lock commit 772296c50e28920ac2611587d21b543df73e0e83 Author: Philipp Krones Date: Mon Sep 25 11:28:58 2023 +0200 Merge commit '7671c283a50b5d1168841f3014b14000f01dd204' into clippyup commit 3112e373aca4250d1444957ab4ded626cb99ee91 Merge: 67ad3c23941 7671c283a50 Author: Philipp Krones Date: Mon Sep 25 11:28:58 2023 +0200 Merge commit '7671c283a50b5d1168841f3014b14000f01dd204' into clippyup commit 7671c283a50b5d1168841f3014b14000f01dd204 Merge: aa137a7e570 903add0c11a Author: bors Date: Mon Sep 25 08:36:06 2023 +0000 Auto merge of #11563 - flip1995:rustup, r=flip1995 Rustup r? `@ghost` changelog: none commit 96ab09dbdd84b7523b1641521dfdf672f64bee17 Merge: 67ad3c23941 efd04b6267f Author: bors Date: Mon Sep 25 08:34:17 2023 +0000 Auto merge of #116138 - RalfJung:miri, r=RalfJung Miri subtree update r? `@ghost` commit 903add0c11a0205314bf49fff6851fea3478449c Author: Philipp Krones Date: Mon Sep 25 10:31:51 2023 +0200 Fix dogfood fallout commit 5eb7604482f8f3264605c0e440861223576d6faf Author: Philipp Krones Date: Mon Sep 25 10:26:33 2023 +0200 Bump nightly version -> 2023-09-25 commit 81fe8dc0848211d5c917f3c2f7a033c2a75bd9be Merge: e2669b27f3c aa137a7e570 Author: Philipp Krones Date: Mon Sep 25 10:26:11 2023 +0200 Merge remote-tracking branch 'upstream/master' into rustup commit efd04b6267f223c273ee0dc7dade7e05e93c824d Merge: d644603b802 085177678e3 Author: bors Date: Mon Sep 25 06:59:01 2023 +0000 Auto merge of #3084 - RalfJung:deadcode, r=RalfJung remove some dead code and add a comment in the AVX test commit 085177678e36d4644346371c29014656b41b54cd Author: Ralf Jung Date: Mon Sep 25 08:56:19 2023 +0200 remove some dead code and add a comment in the AVX test commit d644603b80245e87edcb6ea230e9907c73d8bfa5 Merge: b791f028340 4625e1e8ab5 Author: bors Date: Mon Sep 25 06:10:43 2023 +0000 Auto merge of #3075 - eduardosm:x86-addcarry-subborrow, r=RalfJung Move `llvm.x86.*` shims into `shims::x86` and implement `_addcarry_u32` and `_subborrow_u{32,64}` This PR moves all `llvm.x86.*` shims into `shims::x86` and adds `llvm.x86.addcarry.32`, `llvm.x86.subborrow.32` and `llvm.x86.subborrow.64`. Additionally, it fixes the input carry semantics of `llvm.x86.addcarry.32`. The input carry is an 8-bit value that is interpreted as 1 when it is non-zero. https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html commit 67ad3c23941d2296448d7b38b16eccd1b3e38925 Merge: 8c04c063171 5aba8739d7e Author: bors Date: Mon Sep 25 05:39:09 2023 +0000 Auto merge of #116078 - eduardosm:closure-inherit-target-feature, r=Mark-Simulacrum Add assembly test to make sure that inlining works as expected when closures inherit target features Closes https://github.com/rust-lang/rust/issues/108338 (the added test proves that it is working correctly) commit 4625e1e8ab529ad5393a467dc08c0e5e5b908da9 Author: Eduardo Sánchez Muñoz Date: Sun Sep 24 15:44:52 2023 +0200 Use `cfg` gates in x86 SSE and SSE2 tests commit a617b899960d8b4625354b311f71dea5152d65e8 Author: Eduardo Sánchez Muñoz Date: Fri Sep 22 16:27:27 2023 +0200 Implement `llvm.x86.subborrow.32` and `llvm.x86.subborrow.64` commit 6ec63ed251f25d3c9b3d28321ebacee15d18fdae Author: Eduardo Sánchez Muñoz Date: Thu Sep 21 20:25:36 2023 +0200 Fix the carry semantics of `_addcarry_u32` and `_addcarry_u64` The input carry is an 8-bit value that is interpreted as 1 when it is non-zero. The output carry is an 8-bit value that will be 0 or 1. https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html commit 356039985ea8eaf41ef54b89123bd68019181ef8 Author: Eduardo Sánchez Muñoz Date: Thu Sep 21 20:08:52 2023 +0200 Implement `llvm.x86.addcarry.32` by refactoring `llvm.x86.addcarry.64` to make it generic commit d6b30b88d0cc7b2f98b5f343353f97ef9bf2f9e3 Author: Eduardo Sánchez Muñoz Date: Thu Sep 21 19:41:48 2023 +0200 Move `llvm.x86.*` implementations into `shims::x86` commit a1d181d740df13972533475b4b35d59678b3ab50 Author: Lenko Donchev Date: Wed Jul 5 20:19:14 2023 -0500 Added additional visit steps to visit_generic_param() in order to avoid ICE on no bound vars. commit 8c04c0631719803c99e52db7301586125d30e54a Merge: 5105b1ec58d 0f248d8ea94 Author: bors Date: Mon Sep 25 03:50:59 2023 +0000 Auto merge of #116074 - fzs111:clarify-pin-docs, r=Mark-Simulacrum Clarify example in `Pin::new_unchecked` docs This example in the docs of `Pin::new_unchecked` puzzled me for a relatively long time. Now I understand that it comes down to the difference between dropping the `Pin` vs dropping the pinned value. I have extended the explanation to highlight this difference. In my opinion it is clearer now, and I hope it helps others understand `Pin` better. commit 598f11a1eebbb35f47907519dd59bd7a3d6c2e9e Author: Pouriya Jahanbakhsh Date: Mon Sep 25 06:57:13 2023 +0330 ref(bootstrap.py): add `eprint` function just like `print` but for `stderr` commit 5105b1ec58d61cfeae375d88c30d7f40d7ac0c6a Merge: 91958e0a741 813fed2904f Author: bors Date: Mon Sep 25 00:17:13 2023 +0000 Auto merge of #116057 - RalfJung:io-safety, r=Mark-Simulacrum fix OS-specific I/O safety docs since the io_safety feature is stable Looks like this text was forgotten to be updated when `io_safety` got stabilized: it still says "once the io_safety feature is stable". Also adjust the wording a bit for how these docs relate to the general concept of I/O safety. commit 350ead872058a8be5fc45d27dad59f3bd7e00b6f Author: onur-ozkan Date: Mon Sep 25 01:55:12 2023 +0300 add sanity checks for user write access on `x install` Signed-off-by: onur-ozkan commit 91958e0a7417727a8b65c7f2c163677a8d4ec75d Merge: 37390d65636 26cb34cd182 Author: bors Date: Sun Sep 24 22:25:15 2023 +0000 Auto merge of #116117 - cjgillot:drop-tracking-mir-noscope, r=compiler-errors Remove dead diagnostic code for generators This code has become unreachable with #107421. commit ad509633a261999ba9d73aff908d48da77e0245f Author: Ralf Jung Date: Sun Sep 24 23:38:07 2023 +0200 ConstParamTy: require Eq commit 4f86c69184adc53051a97c658ba9f691665799f5 Author: Ralf Jung Date: Sun Sep 24 23:30:09 2023 +0200 fix ICE due to empty span and empty suggestions commit aa137a7e5705a915ebce592d9476f5dc7d7e5d81 Merge: 94fc43121fb 0433e458dad Author: bors Date: Sun Sep 24 20:58:58 2023 +0000 Auto merge of #11552 - jonboh:ice_threshold_0_enum_variants, r=y21 prevent ice when threshold is 0 and enum has no variants changelog: [`enum_variant_names`]: prevent ice when threshold is 0 and enum has no variants r? `@y21` Fixes the same ice issue raised during review of https://github.com/rust-lang/rust-clippy/pull/11496 commit 37390d65636dd67e263753a3c04fbc60dcc4348e Merge: a1c7a1c89f6 3409ca65d83 Author: bors Date: Sun Sep 24 20:36:44 2023 +0000 Auto merge of #115911 - nebulark:refactor_targetmachine, r=Nilstrieb Add OwnedTargetMachine to manage llvm:TargetMachine LLVMRustDisposeTargetMachine taking a &mut could be undefined behaviour. Wrapping it with a struct and using pointers instead avoids this problem. In addition the TargetMachine is now automatically freed via the Wrappers drop impl. This should fix some memory leaks when create_informational_target_machine was used, e.g. https://github.com/rust-lang/rust/blob/327e6cf55cc5211e19ed46e92e05eef29dc75dd0/compiler/rustc_codegen_llvm/src/llvm_util.rs#L291-L314 r? `@Nilstrieb` commit 99a2fa17e684d4f3f625355561e0e8f9a101cc11 Author: Maybe Waffle Date: Sun Sep 24 20:24:33 2023 +0000 Add a test for printing literals via `proc-macro` commit 285e574b8ebb10ec329210dbcb1782433555d420 Author: Maybe Waffle Date: Sun Sep 24 20:05:27 2023 +0000 Fix `.to_string()` of `proc_macro::Literal` (properly print cstr literals) commit 0433e458dadc927e645f6307c0253a4b241dfd5b Author: Jon Date: Sun Sep 24 21:37:56 2023 +0200 use first instead of get(0) Co-authored-by: Timo <30553356+y21@users.noreply.github.com> commit 3409ca65d835b858d9cefbe8949552f0f5ad0788 Author: Florian Schmiderer Date: Sun Sep 17 14:40:22 2023 +0200 Add OwnedTargetMachine to manage llvm:TargetMachine. Uses pointers instead of &'static mut and provides safe interface to create/dispose it. commit a1c7a1c89f61adc43e9674af3c9c120eb6271a91 Merge: fc61fabc24b 79f3fe48b04 Author: bors Date: Sun Sep 24 18:47:52 2023 +0000 Auto merge of #116120 - GuillaumeGomez:regression-102467, r=compiler-errors Add regression test for #102467 Fixes #102467. r? `@compiler-errors` commit fc61fabc24b94755bb33517a81e81d9981c992ab Merge: 26eeea6a1b9 845a027ddb3 Author: bors Date: Sun Sep 24 16:59:59 2023 +0000 Auto merge of #116116 - Nilstrieb:gate-all-__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, r=compiler-errors Rename the legacy feature gating macro It had a really confusing name by shadowing the previous name, which has caused issues in the past where people added their new syntax in the legacy location. This makes it clear. Also adds a comment about the return type notation gating, which confused me why it was here at first before `@compiler-errors` told me why. commit 5f440dd0696cf54feb560601c7bc383e49511f1a Author: Ben Kimock Date: Sun Sep 24 12:44:54 2023 -0400 GC the Stacked Borrows allocation history commit b3e262acfd711f27c7450379d85092ec169388a7 Author: jonboh Date: Sun Sep 24 18:25:20 2023 +0200 add ui-toml test commit 26eeea6a1b94418a3f513c0cd81f00c4c2966dfd Merge: 70a7fe17432 27fe1c380b4 Author: bors Date: Sun Sep 24 15:16:18 2023 +0000 Auto merge of #116069 - compiler-errors:debug-tuple, r=Nilstrieb Fix debug printing of tuple Self-explanatory. Didn't create a UI test, but I guess I could -- not sure where debug output shows up in rustc_attrs to make a sufficient test, tho. commit 94fc43121fb9a0b3cbb1a70f3063cc131ee12cd0 Merge: d732cce0d39 6e80db96ea9 Author: bors Date: Sun Sep 24 15:09:33 2023 +0000 Auto merge of #11560 - y21:ui-toml-tests, r=Alexendoo Add missing tests for configuration options I noticed that a lot of lints didn't have test(s) for their configuration. This leads to issues like #11481 where the lint just does nothing with it. This PR adds tests for *almost*[^1] all of the lints with a configuration that didn't have a test in ui-toml. The tests that I wrote here are usually two cases: one for where it's right above or under the limit set by the config where it shouldn't lint and another one for right above where it should. changelog: none [^1]: allow-one-hash-in-raw-strings is ignored by needless_raw_string_hashes commit b589976606c7f03b2000bed41ddf6149d96c587b Author: Ralf Jung Date: Sun Sep 24 16:37:19 2023 +0200 use a must_hold variant for checking PartialEq commit 5aba8739d7e57a798a84fe27986d9025d8c8c967 Author: Eduardo Sánchez Muñoz Date: Fri Sep 22 23:19:39 2023 +0200 Add assembly test to make sure that inlining works as expected when closures inherit target features commit c3ed0c454eec4bb7fcf5b73f9d7584390fb692eb Author: Ralf Jung Date: Sun Sep 17 11:04:26 2023 +0200 make sure we always emit the no-PartialEq lint, even if there were other lints commit c5fccb98ea8d853b7d332e077c3ed86401b160c7 Author: Ralf Jung Date: Sat Sep 16 14:15:48 2023 +0200 work towards rejecting consts in patterns that do not implement PartialEq commit 6e80db96ea933676ac9b36714e3af9aaa3eedc00 Author: y21 <30553356+y21@users.noreply.github.com> Date: Sun Sep 24 16:29:26 2023 +0200 use a smaller number in test that fits in usize for 32 bit commit 6ce61d543acd54edfbd3dde5861e3a0bee752cd6 Author: y21 <30553356+y21@users.noreply.github.com> Date: Sun Sep 24 14:56:40 2023 +0200 add missing configuration tests commit 8e558bcf1efd85992cbf60b313d5e0416d0083e3 Author: chenx97 Date: Thu Sep 21 19:40:56 2023 +0800 tidy: remove io-lifetimes from the dependency list commit 141c4636a7c84e45984f3153245e6d29cec1f1d2 Author: chenx97 Date: Thu Sep 21 19:31:01 2023 +0800 deps: update rustix and linux-raw-sys for MIPS R6 commands that perform this update: ```shell cargo +nightly update tempfile clap cargo +nightly update linux-raw-sys rustix ``` commit 79f3fe48b04fcf4a87316a2e61b098153d959657 Author: Guillaume Gomez Date: Sun Sep 24 14:09:38 2023 +0200 Add regression test for #102467 commit 70a7fe174321284ab262b64941b123ad081af242 Merge: c7224e3c954 09c5f983e3e Author: bors Date: Sun Sep 24 11:40:45 2023 +0000 Auto merge of #116076 - chriswailes:android-riscv-extension-update, r=cjgillot Add Zba, Zbb, and Zbs as target features for riscv64-linux-android This pull request adds the Zba, Zbb, and Zbs target features to the `riscv64-linux-android` target specification. These features have been enabled and tested internally in Android infrastructure. commit b791f0283406b1397209cf3aaf59c6c35b2348b5 Merge: 00a8d4830e7 413ff386c23 Author: bors Date: Sun Sep 24 11:34:00 2023 +0000 Auto merge of #3081 - eduardosm:avx512-tests, r=RalfJung Put AVX512 tests together commit 413ff386c235b45e6ce7fcea022fcdc5ac86feb2 Author: Eduardo Sánchez Muñoz Date: Sun Sep 24 11:57:53 2023 +0200 Put AVX512 tests together commit c7224e3c954ce54853364c950608c1f0ed47ea85 Merge: 44bd31c2163 984ecefed8a Author: bors Date: Sun Sep 24 09:47:30 2023 +0000 Auto merge of #105861 - Ayush1325:uefi-std-minimial, r=workingjubilee Add Minimal Std implementation for UEFI # Implemented modules: 1. alloc 2. os_str 3. env 4. math # Related Links Tracking Issue: https://github.com/rust-lang/rust/issues/100499 API Change Proposal: https://github.com/rust-lang/libs-team/issues/87 # Additional Information This was originally part of https://github.com/rust-lang/rust/pull/100316. Since that PR was becoming too unwieldy and cluttered, and with suggestion from `@dvdhrm,` I have extracted a minimal std implementation to this PR. The example in `src/doc/rustc/src/platform-support/unknown-uefi.md` has been tested for `x86_64-unknown-uefi` and `i686-unknown-uefi` in OVMF. It would be great if someone more familiar with AARCH64 can help with testing for that target. Signed-off-by: Ayush Singh commit 26cb34cd182b57f6595bc64f1c9f5498fbadadeb Author: Camille GILLOT Date: Thu Aug 3 15:56:56 2023 +0000 Remove span from BrAnon. commit b2ff77cb78165d221438a1b8496819075e5a90eb Author: Camille GILLOT Date: Sat Sep 23 07:56:59 2023 +0000 Do not clone valtree and slice constants. commit 5f9d64d72f043ccf5bfe99a1fbd570b0256ab4db Author: Camille GILLOT Date: Wed Apr 12 18:39:56 2023 +0000 Embed simplification into VnState. commit 33115367404c7e860853054c53e7ad613258516b Author: Camille GILLOT Date: Sat Jul 1 14:57:29 2023 +0000 Workaround issue 112651. commit 6dfa05369767d7c079618d93d8bab53415721f65 Author: Camille GILLOT Date: Sun May 14 20:31:02 2023 +0000 Complete miri test. commit 644e40f536840d3bab28cab985a034eabbf707d4 Author: Camille GILLOT Date: Sun May 14 13:27:07 2023 +0000 Do not assume anything about repeated reification of generic functions. commit db50bd96e50cc7debb1734e1f6d5318f5e0b3095 Author: Camille GILLOT Date: Sat May 13 22:05:24 2023 +0000 Add a paragraph about the assume bitwise equal. commit 1ea93998031d7bb6559ee50bb6b4d04ff4f5f035 Author: Camille GILLOT Date: Mon May 1 09:59:00 2023 +0000 Do not check copiability. commit 6fa55d0aff000b8a01825dbedf9e2fdf046fd726 Author: Camille GILLOT Date: Sun Apr 9 11:15:48 2023 +0000 Add documentation. commit 8b848af325268f3e07bcdcc4cfb956e547980f2f Author: Camille GILLOT Date: Mon Mar 20 18:05:07 2023 +0000 Add global value numbering pass. commit ded1a8b026205167fd427743a8920c10fecd4888 Author: Camille GILLOT Date: Thu Aug 3 15:30:26 2023 +0000 Remove dead code. commit 845a027ddb3750bb841d0676b7eb460b7c1a2f9d Author: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun Sep 24 10:47:31 2023 +0200 Add comment about RTN feature gating commit 073feb5e69c762bffc53e615d2fde844e0d08a92 Author: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun Sep 24 10:44:31 2023 +0200 Rename the legacy feature gating macro It had a really confusing name by shadowing the previous name, which has caused issues in the past where people added their new syntax in the legacy location. This makes it clear. commit 44bd31c2163c944dbf061f52418900b11e1b707c Merge: 551c7183f8a f286a756924 Author: bors Date: Sun Sep 24 07:59:00 2023 +0000 Auto merge of #116075 - Colonial-Dev:issue-116063-fix, r=Mark-Simulacrum Document panics on unsigned wrapping_div/rem calls (#116063) Add missing `# Panics` sections to the `uint_impl!` macro, documenting that the `wrapping_rem/div` calls will panic if passed zero. commit 551c7183f8ae46c4b4fd0237acbdc937670bf74a Merge: 8a6bae28247 b8c85207250 Author: bors Date: Sun Sep 24 06:13:17 2023 +0000 Auto merge of #115794 - cjgillot:aggregate-no-box, r=davidtwco Do not create a DerefLen place for `Box<[T]>`. Fixes https://github.com/rust-lang/rust/issues/115789 commit 00a8d4830e700d7f53e176a4e042f54495dd8365 Merge: 5ddf866c9c9 cf766029b65 Author: bors Date: Sun Sep 24 05:21:27 2023 +0000 Auto merge of #3079 - rust-lang:rustup-2023-09-24, r=saethlin Automatic sync from rustc commit cf766029b6502cedac0be9104fd7589b7abd8de9 Author: The Miri Conjob Bot Date: Sun Sep 24 05:14:40 2023 +0000 fmt commit 8ae7c743bbc6e6281c5aa892daaaa5439aafc1db Merge: fdbf9324995 42ca6e4e576 Author: The Miri Conjob Bot Date: Sun Sep 24 05:12:12 2023 +0000 Merge from rustc commit fdbf9324995517752d0387cf5fa5ebce519fb8e7 Author: The Miri Conjob Bot Date: Sun Sep 24 05:03:58 2023 +0000 Preparing for merge from rustc commit 8a6bae28247fbaa3257856e00d084ac8c90712f3 Merge: 42ca6e4e576 d63959f2faa Author: bors Date: Sun Sep 24 04:23:43 2023 +0000 Auto merge of #115416 - c410-f3r:match_cfg, r=Amanieu Add the `cfg_match!` macro # Movitation Adds a match-like version of the `cfg_if` crate without a RFC [for the same reasons that caused `matches!` to be included in the standard library](https://github.com/rust-lang/rust/pull/65479). * General-purpose (not domain-specific) * Simple (the implementation is short) and useful (things can become difficult with several `cfg`s) * Very popular [on crates.io ](https://crates.io/crates/cfg-if) (currently 3th in all-time downloads) * The two previous points combined make it number three in [left-pad index](https://twitter.com/bascule/status/1184523027888988160) score ```rust match_cfg! { cfg(unix) => { fn foo() { /* unix specific functionality */ } } cfg(target_pointer_width = "32") => { fn foo() { /* non-unix, 32-bit functionality */ } } _ => { fn foo() { /* fallback implementation */ } } } ``` # Considerations A match-like syntax feels more natural in the sense that each macro fragment resembles an arm but I personally don't mind switching to any other desired syntax. The lack of `#[ ... ]` is intended to reduce typing, nevertheless, the same reasoning described above can also be applied to this aspect. Since blocks are intended to only contain items, anything but `cfg` is not expected to be supported at the current or future time. ~~Credits goes to `@gnzlbg` because most of the code was shamelessly copied from https://github.com/gnzlbg/match_cfg.~~ Credits goes to `@alexcrichton` because most of the code was shamelessly copied from https://github.com/rust-lang/cfg-if. commit 42ca6e4e5760a548a6fa858482de6d237f6fb3b8 Merge: 0f2a9ce53e4 2044a2d7fa1 Author: bors Date: Sun Sep 24 02:35:05 2023 +0000 Auto merge of #104385 - BlackHoleFox:apple-minimum-bumps, r=petrochenkov Raise minimum supported Apple OS versions This implements the proposal to raise the minimum supported Apple OS versions as laid out in the now-completed MCP (https://github.com/rust-lang/compiler-team/issues/556). As of this PR, rustc and the stdlib now support these versions as the baseline: - macOS: 10.12 Sierra - iOS: 10 - tvOS: 10 - watchOS: 5 (Unchanged) In addition to everything this breaks indirectly, these changes also erase the `armv7-apple-ios` target (currently tier 3) because the oldest supported iOS device now uses ARMv7s. Not sure what the policy around tier3 target removal is but shimming it is not an option due to the linker refusing. [Per comment](https://github.com/rust-lang/compiler-team/issues/556#issuecomment-1297175073), this requires a FCP to merge. cc `@wesleywiser.` commit 910674f1c4d1551ffab71627e1821cf8298f3669 Author: DianQK Date: Sun Sep 24 09:46:04 2023 +0800 Only check for successful vectorization on wider_reduce_into_iter Different vectorization results are due to different LLVM versions. commit 0f2a9ce53e49ad6c80266cacc0b97444b17ea36b Merge: acfb46db5a0 164517c4584 Author: bors Date: Sun Sep 24 00:52:43 2023 +0000 Auto merge of #116112 - matthiaskrgr:rollup-s3cm2f7, r=matthiaskrgr Rollup of 5 pull requests Successful merges: - #116073 (Allow higher-ranked fn sigs in `ValuePairs`) - #116082 (Tweak expected message to explain what it's actually signifying) - #116086 (More accurate suggestion for `self.` and `Self::`) - #116104 (Reuse calculate_debuginfo_offset for fragments.) - #116106 (Migrate GUI colors test to original CSS color format) r? `@ghost` `@rustbot` modify labels: rollup commit 2044a2d7fa1de37aef704443dc127e5072a5d04c Author: BlackHoleFox Date: Sun Nov 13 17:25:56 2022 -0600 Raise minimum supported tvOS version to 10.0 commit 3b52befdcec6b43163c937ed6e842c1c49846052 Author: BlackHoleFox Date: Sun Nov 13 17:23:26 2022 -0600 Raise minimum supported iOS version to 10.0 Drop the armv7-apple-ios target too because its no longer supported with the hardware iOS 10 requires. commit 58bbca958d917a89124da248735926f86c59a149 Author: BlackHoleFox Date: Sun Nov 13 16:58:18 2022 -0600 Raise minimum supported macOS to 10.12 commit 164517c45847d816b6c7149a626f5d42bfe3701f Merge: 2fd7acf4e3e 2d25a25e5dc Author: Matthias Krüger Date: Sun Sep 24 01:14:07 2023 +0200 Rollup merge of #116106 - GuillaumeGomez:migrate-gui-test-color-42, r=notriddle Migrate GUI colors test to original CSS color format Follow-up of https://github.com/rust-lang/rust/pull/111459. And with this one I'm finally done with this migration. r? ``@notriddle`` commit 2fd7acf4e3e5bf61fa2a2b8aaeb59adbed791e03 Merge: 61b38b216a6 8ec5639bc20 Author: Matthias Krüger Date: Sun Sep 24 01:14:07 2023 +0200 Rollup merge of #116104 - cjgillot:calculate_debuginfo_offset, r=b-naber Reuse calculate_debuginfo_offset for fragments. This removes a little code duplication. commit 61b38b216a683af2f5df42c036c52c5bee34ef1c Merge: 8c9e516e6e9 7d8559ac907 Author: Matthias Krüger Date: Sun Sep 24 01:14:06 2023 +0200 Rollup merge of #116086 - estebank:issue-115992, r=compiler-errors More accurate suggestion for `self.` and `Self::` Detect that we can't suggest `self.` in an associated function without `&self` receiver. Partially address #115992. r? ``@compiler-errors`` commit 8c9e516e6e97bd8a03f6d171ee3f678e43ee7858 Merge: d92a1bd7ccc 82e7cec16d7 Author: Matthias Krüger Date: Sun Sep 24 01:14:06 2023 +0200 Rollup merge of #116082 - compiler-errors:default-assoc-ty-msg, r=estebank Tweak expected message to explain what it's actually signifying r? ``@estebank`` since you added this commit d92a1bd7ccc42f4d8502f988974c3bac667f0058 Merge: 13e6f24b9ad 8cfd249198d Author: Matthias Krüger Date: Sun Sep 24 01:14:05 2023 +0200 Rollup merge of #116073 - compiler-errors:poly-sigs, r=b-naber Allow higher-ranked fn sigs in `ValuePairs` For better bookkeeping -- only affects diagnostic path. Allow reporting signature mismatches like "signature"s and not "fn pointer"s. Improves https://github.com/rust-lang/rust/pull/115897#discussion_r1331940846 commit acfb46db5a01fec939a28f2cd80f24289d903d71 Merge: 13e6f24b9ad 74f52613454 Author: bors Date: Sat Sep 23 22:38:45 2023 +0000 Auto merge of #112711 - Emilgardis:lit_byte_char, r=dtolnay implement Literal::byte_character without this, the only way to create a `LitKind::Byte` is by doing `"b'a'".parse::()`, this solves that by enabling `Literal::byte_character(b'a')` cc #71358 The tracking issue is #115268 commit ba8d53dc8fd43fac0e539fee9c91fcdd307cc17e Author: John Kåre Alsaker Date: Wed Sep 20 15:38:18 2023 +0200 Don't use a thread to load the dep graph commit 74f52613454714cd033165cc635a407ef61f04c2 Author: Emil Gardström Date: Sat Sep 23 20:48:00 2023 +0200 implement Literal::byte_character without this, the only way to create a `LitKind::Byte` is by doing `"b'a'".parse::()`, this solves that by enabling `Literal::byte_character(b'a')` commit 863d2fddd79c3096cd421278dab420d1f3b0de63 Author: onur-ozkan Date: Sat Sep 23 23:58:43 2023 +0300 Pass `-jN` from Make to `BOOTSTRAP_ARGS` Enables the same functionality as `x -jN` in Make by passing the `-jN` arg from Make to the `BOOTSTRAP_ARGS` args if it is specified. Signed-off-by: onur-ozkan commit ab8307331af0ecbd1b94a0dc1f94c0b78776a8c4 Author: Ralf Jung Date: Sat Sep 23 21:30:45 2023 +0200 also make platform_intrinsics internal commit 13e6f24b9adda67852fb86538541adaa68aff6e8 Merge: 19c65022fc1 bffb3467e17 Author: bors Date: Sat Sep 23 18:28:00 2023 +0000 Auto merge of #107421 - cjgillot:drop-tracking-mir, r=oli-obk Enable -Zdrop-tracking-mir by default This PR enables the `drop-tracking-mir` flag by default. This flag was initially implemented in https://github.com/rust-lang/rust/pull/101692. This flag computes auto-traits on generators based on their analysis MIR, instead of trying to compute on the HIR body. This removes the need for HIR-based drop-tracking, as we can now reuse the same code to compute generator witness types and to compute generator interior fields. commit 39f7f695dab8287c06adf04dc0a8d46f6ce1e2be Author: Alex Macleod Date: Sat Sep 23 18:11:56 2023 +0000 Add msrv test template for `cargo dev new_lint --msrv` commit 2d25a25e5dc5636778d1e4e86bf6fa2d9a1be0af Author: Guillaume Gomez Date: Sat Sep 23 20:03:03 2023 +0200 Migrate GUI colors test to original CSS color format commit d63959f2faa0a3e1164dd42c641685de1fcad295 Author: Caio Date: Sat Sep 23 14:23:51 2023 -0300 Add the `cfg_match!` macro commit 19c65022fc1ad9cc3d3dcf50a0bdf50e4ab572ab Merge: 3050938abd4 d5ec9af09da Author: bors Date: Sat Sep 23 16:38:20 2023 +0000 Auto merge of #116047 - a-lafrance:I80836-codegen-test, r=Mark-Simulacrum Add codegen test to guard against VecDeque optimization regression Very small PR that adds a codegen test to guard against regression for the `VecDeque` optimization addressed in #80836. Ensures that Rustc optimizes away the panic when unwrapping the result of `.get(0)` because of the `!is_empty()` condition. commit 0f248d8ea9403850cd3d80b370fcc9b6793f17b1 Author: FZs <39064892+fzs111@users.noreply.github.com> Date: Fri Sep 22 19:33:33 2023 +0200 Clarify example in `Pin::new_unchecked` docs commit 93863383c8240c35f6bfda97ab96fd5ce8a5783c Author: Eduardo Sánchez Muñoz Date: Fri Sep 22 20:44:56 2023 +0200 Avoid overflow in `IoSlice::advance_slices` commit bdd66b3f98e8c3907aad82f16726f0a233ea4ba8 Author: onur-ozkan Date: Sat Sep 23 17:08:43 2023 +0300 allow LTO on `proc-macro` crates with `-Zdylib-lto` Signed-off-by: onur-ozkan commit ac0683b78310bba9c3c601cfd81bbda4a10be322 Author: Camille GILLOT Date: Sat Sep 23 09:35:44 2023 +0000 Use correct offset when codegening mir::Const::Indirect. commit 699240567446ba9d794b7e4883831ae13aadac59 Author: Camille GILLOT Date: Tue Sep 19 19:20:22 2023 +0000 Tolerate non-ptr indirect scalars in codegen. commit 8ec5639bc204217cf0a37ba92d35358f787b6d69 Author: Camille GILLOT Date: Tue Sep 5 17:14:37 2023 +0000 Reuse calculate_debuginfo_offset for fragments. commit e2669b27f3cd32fbf956bfcae96c3e19f49108a1 Author: Camille GILLOT Date: Thu Aug 3 13:47:04 2023 +0000 Remove GeneratorWitness and rename GeneratorWitnessMIR. commit bffb3467e1707a9d4fbff73fa6a7ed40cad5170b Author: Camille GILLOT Date: Sat Sep 23 13:03:14 2023 +0000 Make test more robust to opts. commit 19e160fe2fa0c8f04dc2b550db32f690ae27c64b Author: Camille GILLOT Date: Sat Jan 28 23:20:02 2023 +0000 Bless clippy. commit 44ac8dcc71c908aa320ccb51717ab2a0a8262b1d Author: Camille GILLOT Date: Thu Aug 3 13:47:04 2023 +0000 Remove GeneratorWitness and rename GeneratorWitnessMIR. commit 855a75b6d68084dd98383f37950da43c87476f0d Author: Camille GILLOT Date: Thu Aug 3 13:25:26 2023 +0000 Remove useless wrapper. commit baa64b0e77007a31ce0cfaada5300b536f951d2f Author: Camille GILLOT Date: Wed Jun 7 17:43:17 2023 +0000 Remove dead error code. commit 6aa1268900506d5004c681e07b868db0cfc683fe Author: Camille GILLOT Date: Sat Jan 28 23:20:02 2023 +0000 Bless clippy. commit d989e14cf2885b483a443875a0974ca25e902f24 Author: Camille GILLOT Date: Sat Jan 28 18:49:48 2023 +0000 Bless mir-opt commit 211d2ed07bb5dff7683fb021341db751cec2ca1e Author: Camille GILLOT Date: Sat Jun 24 10:02:54 2023 +0000 Bless tests. commit 0a2d39de2e0b87361432ae695cc84ad74d09972a Author: Camille GILLOT Date: Sat Jan 28 12:56:04 2023 +0000 Enable drop_tracking_mir by default. commit 286502c9ed77e49aea5bb89cf18c5eda3a8fce92 Author: Camille GILLOT Date: Sat Jan 28 12:56:04 2023 +0000 Enable drop_tracking_mir by default. commit a626caaad97b7f8733b8c9bd1fe9662cfc1e3ec1 Author: Camille GILLOT Date: Sun May 7 18:38:52 2023 +0000 Revert duplication of tests. commit ff032043653e7aebfbf74ab59572f929aa2beb65 Author: Camille GILLOT Date: Sat Jun 3 08:38:44 2023 +0000 Fold lifetimes before substitution. commit 9450b75986571785b11d202e68af255a1780f68f Author: Camille GILLOT Date: Tue May 16 10:47:50 2023 +0000 Do not construct def_path_str for MustNotSuspend. commit b6836849acf8ce97e71fdf3963e4000173f8e1da Author: Eduardo Sánchez Muñoz Date: Sat Sep 23 13:21:50 2023 +0200 Add regression test for issue #79865 commit 3050938abd423f9e37466cc4cd4129c9b8cc427c Merge: 0237aa3d771 79d685325c1 Author: bors Date: Sat Sep 23 10:01:49 2023 +0000 Auto merge of #116081 - compiler-errors:closure-captures-sized, r=cjgillot Check that closure/generator's interior/capture types are sized check that closure upvars and generator interiors are sized. this check is only necessary when `unsized_fn_params` or `unsized_locals` is enabled, so only check if those are active. Fixes #93622 Fixes #61335 Fixes #68543 commit 0237aa3d771f4c6152c7d46a888ea89c538b121e Merge: 136d74fab85 58ef3a0ec9a Author: bors Date: Sat Sep 23 08:11:59 2023 +0000 Auto merge of #116045 - notriddle:notriddle/issue-83556, r=cjgillot diagnostics: avoid mismatch between variance index and hir generic This happens because variances are constructed from ty generics, and ty generics are always constructed with lifetimes first. https://github.com/rust-lang/rust/blob/b3aa8e7168a3d940122db3561289ffbf3f587262/compiler/rustc_hir_analysis/src/collect/generics_of.rs#L248-L269 Fixes #83556 commit 37acbbb4b51b8d390f19fa5877cdd3d36bc5ff0f Author: Ralf Jung Date: Sat Sep 23 08:39:36 2023 +0200 make link_llvm_intrinsics feature internal commit 136d74fab8503366fa8b2eb9099f9d7f1b4cb5ec Merge: bf982631df8 d3dea30cb4c Author: bors Date: Sat Sep 23 06:25:41 2023 +0000 Auto merge of #116071 - estebank:issue-115905, r=compiler-errors Point at cause of expectation of `break` value when possible When encountering a type error within the value of a `break` statement, climb the HIR tree to identify if the expectation comes from an assignment or a return type (if the loop is the tail expression of a `fn`). Fix #115905. commit 58ef3a0ec9a3e2151a103964683b5d00932304d8 Author: Michael Howell Date: Fri Sep 22 22:41:01 2023 -0700 diagnostics: simpler 83556 handling by bailing out commit 5ddf866c9c91afa53d26a3bf13c2cce4dd8bb21d Merge: a0defe0a26d 3ca49cfe9d0 Author: bors Date: Sat Sep 23 05:33:22 2023 +0000 Auto merge of #3077 - rust-lang:rustup-2023-09-23, r=saethlin Automatic sync from rustc commit 3ca49cfe9d0ab73f3ee33f6f216b1d001f7cd073 Merge: 68706342323 79d685325c1 Author: The Miri Conjob Bot Date: Sat Sep 23 05:17:05 2023 +0000 Merge from rustc commit 68706342323af86d58595d43a725637b42783675 Author: The Miri Conjob Bot Date: Sat Sep 23 05:10:33 2023 +0000 Preparing for merge from rustc commit bf982631df866498a295528ff0047207e881d55d Merge: 2d08657901d 4ed4913e67c Author: bors Date: Sat Sep 23 04:41:09 2023 +0000 Auto merge of #116052 - oli-obk:ceci_nest_pas_une_query, r=WaffleLapkin Add a way to decouple the implementation and the declaration of a TyCtxt method. properly addresses https://github.com/rust-lang/rust/pull/115819 accepted MCP: https://github.com/rust-lang/compiler-team/issues/395 commit 3da69c704112cf38297ae878a3f1d7e7ab014897 Merge: 835d7d923b7 5ee167e00d0 Author: bors Date: Sat Sep 23 04:41:09 2023 +0000 Auto merge of #116052 - oli-obk:ceci_nest_pas_une_query, r=WaffleLapkin Add a way to decouple the implementation and the declaration of a TyCtxt method. properly addresses https://github.com/rust-lang/rust/pull/115819 accepted MCP: https://github.com/rust-lang/compiler-team/issues/395 commit 79d685325c170f0aed483e4c50c1f2b7d5b2bdc1 Author: Michael Goulet Date: Sat Sep 23 04:03:24 2023 +0000 Check types live across yields in generators too commit c21867f9f6af92c4669b1ee7541291d7b9635b1a Author: Michael Goulet Date: Sat Sep 23 00:26:26 2023 +0000 Check that closure's by-value captures are sized commit 2d08657901d8fec8f51f203dc8a38e25c162e834 Merge: 55b5c7bfde6 5db9a5ee385 Author: bors Date: Sat Sep 23 02:23:44 2023 +0000 Auto merge of #116066 - weihanglo:update-cargo, r=weihanglo Update cargo 19 commits in b4ddf95ad9954118ac0dae835f2966394ad04c02..414d9e3a6d8096f3e276234ce220c868767a8792 2023-09-18 03:48:09 +0000 to 2023-09-22 07:03:57 +0000 - refactor(TomlManifest): fail when package_root is not a directory (rust-lang/cargo#12722) - Better suggestion for unsupported mode in build command (rust-lang/cargo#12693) - Update curl-sys to pull in curl 8.3.0 (rust-lang/cargo#12718) - chore(ci): Ignore patch version in MSRV (rust-lang/cargo#12716) - refactor: move cached crates.io SourceID to config module (rust-lang/cargo#12711) - fix: typos in registry authentication documentation (rust-lang/cargo#12714) - doc: mention unstable flag `-Z asymmetric-token` (rust-lang/cargo#12712) - fix: copy PDBs for EFI targets (rust-lang/cargo#12688) - infra: add auto-trigger rules for new labels (rust-lang/cargo#12713) - fix: use channel-specific link for registry auth error (rust-lang/cargo#12709) - Add some enhancements to `cargo clean` (rust-lang/cargo#12638) - chore: Fix typos (rust-lang/cargo#12707) - Shortest path (rust-lang/cargo#12678) - doc/reference/manifest: Adjust `keywords` description (rust-lang/cargo#12705) - Cargo add displays either feature list or summarized count (rust-lang/cargo#12702) - SemVer: Update documentation about removing optional dependencies (rust-lang/cargo#12687) - publish.py: Remove obsolete `sleep()` calls (rust-lang/cargo#12686) - generalise suggestion on abiguous spec (rust-lang/cargo#12685) - util/toml: Remove duplicate `serde(rename)` attributes (rust-lang/cargo#12682) r? ghost commit 7d8559ac9077e35a687d5b16f17f2f493421f3ab Author: Esteban Küber Date: Sat Sep 23 01:59:22 2023 +0000 Add test commit ac5e18756a4f0987c5861e45b82ac6f410fd4734 Author: Esteban Küber Date: Sat Sep 23 01:54:05 2023 +0000 Tweak wording and logic commit 0e986825762edd031bc6bf4a78d9162ac2ed6268 Author: Esteban Küber Date: Sat Sep 23 01:47:06 2023 +0000 When encountering method on `Self` that we can't suggest, mention it commit c4a4926083e9f0b9aeef549f93cb66cd9d4076d7 Author: Esteban Küber Date: Sat Sep 23 01:34:50 2023 +0000 More accurate suggestion for `self.` and `Self::` Fix #115992. commit d128b8ba10a1949bbac7794c77a2738db76e2229 Author: Josh Stone Date: Fri Sep 22 18:06:00 2023 -0700 Add release notes for 1.73.0 commit 82e7cec16d7143907f145c895f7208c0a3906e03 Author: Michael Goulet Date: Sat Sep 23 00:56:43 2023 +0000 Tweak expected message to explain what it's actually signifying commit a0defe0a26d6ccf3ed6f8ed803547b5dd50c7d4f Merge: ce33ca0a1e5 b075a9d2ab4 Author: bors Date: Sat Sep 23 00:38:26 2023 +0000 Auto merge of #3072 - eduardosm:llvm.ctpop, r=saethlin Implement `llvm.ctpop.v*` intrinsics Tested through x86 avx512vpopcntdq and avx512bitalg functions. I picked them from https://github.com/rust-lang/miri/issues/2057#issuecomment-1716309674, which looked easy. commit 55b5c7bfde6247db5e4d2e3efe353e13849bb233 Merge: e4133ba9b1a 9090ed81198 Author: bors Date: Sat Sep 23 00:25:14 2023 +0000 Auto merge of #115695 - tmiasko:compiletest-supported-sanitizers, r=oli-obk compiletest: load supported sanitizers from target spec commit d3dea30cb4c2f035ea8621dc266babb3a7be79b4 Author: Esteban Küber Date: Fri Sep 22 18:42:22 2023 +0000 Point at cause of expectation of `break` value when possible Fix #115905. commit f286a756924eddfada894b05246e559262a6bd38 Author: James Haywood Date: Fri Sep 22 18:07:17 2023 -0400 Extend fix to wrapping_div, wrapping_div_euclid and wrapping_rem_euclid commit e4133ba9b1a150ef624f5d189913a37405f4414c Merge: aadb5718dd9 efee13ab335 Author: bors Date: Fri Sep 22 21:46:07 2023 +0000 Auto merge of #116077 - matthiaskrgr:rollup-2y1buzg, r=matthiaskrgr Rollup of 6 pull requests Successful merges: - #115770 (Match on elem first while building move paths) - #115999 (Capture scrutinee of if let guards correctly) - #116056 (Make unsized casts illegal) - #116061 (Remove TaKO8Ki from review rotation) - #116062 (Change `start` to `#[start]` in some diagnosis) - #116067 (Open the FileEncoder file for reading and writing) r? `@ghost` `@rustbot` modify labels: rollup commit d732cce0d39d49ad07feb45d5f6d966a69d0147c Merge: 50139e6ad28 7e46fb9a658 Author: bors Date: Fri Sep 22 21:19:28 2023 +0000 Auto merge of #11553 - mickvangelderen:fix-large-futures-example, r=xFrednet Fix large_futures example The value used in the large_futures example was not large enough to trigger the lint given the default threshold. The example also contained more code than necessary. This PR changes the value size from 1kB to 16kB and reduces the example in size. changelog: [`large_futures`]: Fix and simplify example commit efee13ab33572c3f8ea2eb88886d15c8a13c4d0b Merge: 952d6608fc9 09960e03194 Author: Matthias Krüger Date: Fri Sep 22 23:12:38 2023 +0200 Rollup merge of #116067 - saethlin:meta-stats-ice, r=WaffleLapkin Open the FileEncoder file for reading and writing Maybe I just don't know `File` well enough, but the previous comment didn't make it clear enough to me that we can't use `File::create`. This one does. Fixes https://github.com/rust-lang/rust/issues/116055 r? `@WaffleLapkin` commit 952d6608fc9678bfc681d3bb33d7c09fdf6a69d6 Merge: 81b98f6fa4e 17dfabff9c1 Author: Matthias Krüger Date: Fri Sep 22 23:12:37 2023 +0200 Rollup merge of #116062 - eduardosm:start-fn-diag, r=WaffleLapkin Change `start` to `#[start]` in some diagnosis They refer to a function with the `start` attribute, but not necessarily named `start`. commit 81b98f6fa4e701b9115a96f29fd598154995a57a Merge: a38f2309fc7 8e06b25e390 Author: Matthias Krüger Date: Fri Sep 22 23:12:36 2023 +0200 Rollup merge of #116061 - Nilstrieb:Nilstrieb-patch-1, r=TaKO8Ki Remove TaKO8Ki from review rotation `@TaKO8Ki` you haven't been actively reviewing pull requests lately, so I'm removing you from the rotation. Thank you for all the PRs you have reviewed when you were more actively, it was very helpful! Feel free to add yourself back when you have more time 💜 r? `@wesleywiser` `@davidtwco` commit a38f2309fc7148ba94c136bfe28bbcfc4a8495d7 Merge: e6f4b35d9f8 861448b426d Author: Matthias Krüger Date: Fri Sep 22 23:12:36 2023 +0200 Rollup merge of #116056 - ouz-a:wide_ice, r=compiler-errors Make unsized casts illegal Weirdly enough this https://github.com/rust-lang/rust/issues/115998 issue seems to exist since Rust 1.0 (couldn't check before that) but it's only recently been noticed. This change makes those casts illegal. Fixes https://github.com/rust-lang/rust/issues/115998 commit e6f4b35d9f8f512b71a99dab774e2276322720f3 Merge: d4d0c840b3e d4ffb3b08aa Author: Matthias Krüger Date: Fri Sep 22 23:12:35 2023 +0200 Rollup merge of #115999 - matthewjasper:closure-capture-let-guards, r=b-naber Capture scrutinee of if let guards correctly Previously we were always capturing by value. cc #51114 commit d4d0c840b3eb1f8fc3da8e1a79e0d5e50a9fe1c5 Merge: 959b2c703d4 63df126f596 Author: Matthias Krüger Date: Fri Sep 22 23:12:34 2023 +0200 Rollup merge of #115770 - ouz-a:match_elem_builder, r=lcnr Match on elem first while building move paths While working on https://github.com/rust-lang/rust/pull/115025 `@lcnr` and I observed "move_paths_for" function matched on the `Ty` instead of `Projection` which seems flawed as it's the `Projection`s that cause the problem not the type. r? `@lcnr` commit 50139e6ad282b153439dd2ae6bf380484f60dfbf Merge: 33f084ef78f ab51f66ec08 Author: bors Date: Fri Sep 22 21:07:46 2023 +0000 Auto merge of #11551 - Meczka:fix-fp-needless-pass-by-ref-mut, r=xFrednet fixed fp caused by moving &mut reference inside of a closure changelog: [`needless_pass_by_ref mut`]: fixes false positive caused by not covering mutable references passed to a closure inside of a fuction fixes #11545 commit 09c5f983e3ed388df406fe006c2baf89d03aec22 Author: Chris Wailes Date: Fri Sep 22 13:32:37 2023 -0700 Add Zba, Zbb, and Zbs as target features for riscv64-linux-android commit 4ed4913e67cab329bd3cca92dff1cf558cc3575e Author: Oli Scherer Date: Fri Sep 22 16:38:31 2023 +0000 Merge `ExternProviders` into the general `Providers` struct commit 09960e03194626738b3533b6c2d06a0c505117d3 Author: Ben Kimock Date: Fri Sep 22 12:34:30 2023 -0400 Open the FileEncoder file for reading and writing commit aadb5718dd9a2f4b9c64893baedfe1f5991d6bbd Merge: 959b2c703d4 8d81d5a9095 Author: bors Date: Fri Sep 22 19:57:07 2023 +0000 Auto merge of #116001 - fmease:validate-crate-name-extern-cli-opt, r=est31 [breaking change] Validate crate name in `--extern` [MCP 650] Reject non-ASCII-identifier crate names passed to the CLI option `--extern` (`rustc`, `rustdoc`). Implements [MCP 650](https://github.com/rust-lang/compiler-team/issues/650) (except that we only allow ASCII identifiers not arbitrary Rust identifiers). Fixes #113035. [As mentioned on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Disallow.20non-identifier-valid.20--extern.20cr.E2.80.A6.20compiler-team.23650/near/376826988), doing a crater run probably doesn't make sense since it wouldn't yield anything. Most users don't interact with `rustc` directly but only ever through Cargo which always passes a valid crate name to `--extern` when it invokes `rustc` and `rustdoc`. In any case, the user wouldn't be able to use such a crate name in the source code anyway. Note that I'm not using [`rustc_session::output::validate_crate_name`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/output/fn.validate_crate_name.html) (used for `--crate-name` and `#![crate_name]`) since the latter doesn't reject non-ASCII crate names and ones that start with a digit. As an aside, I've also thought about getting rid of `validate_crate_name` entirely in a separate PR (with another MCP) in favor of `is_ascii_ident` to reject more weird `--crate-name`s, `#![crate_name]`s and file names but I think that would lead to a lot of actual breakage, namely because of file names starting with a digit. In `tests/ui` 9 tests would be impacted for example. CC `@estebank` r? `@est31` commit 1170b7b4478ed1674e0b498dfa52f0f68f6426c8 Author: James Haywood Date: Fri Sep 22 15:52:07 2023 -0400 Resolve rust-lang/rust#116063 commit 8cfd249198dd0e04558d725452b91f4db3984633 Author: Michael Goulet Date: Fri Sep 22 19:47:34 2023 +0000 Allow higher-ranked fn sigs in ValuePairs commit 85681219963220bd5e3bea0545b91eb7b340249a Author: Michael Goulet Date: Fri Sep 22 18:55:37 2023 +0000 Need to use hybrid param-env to make sure implication is not circular commit b5a904a9d450c2afbefcc0c95974f3396e73d487 Author: Michael Goulet Date: Fri Sep 22 18:45:53 2023 +0000 Use placeholders to prevent using inferred RPITIT types to imply their own WF-ness commit 984ecefed8a12fc31200f5307f07acd7ce6b18c9 Author: Ayush Singh Date: Thu Sep 21 18:59:43 2023 +0530 Fixes from PR - Hide Docs - Use repr_unpacked error Signed-off-by: Ayush Singh commit 27fe1c380b481304a75411ac96cac52d5a8f6c2c Author: Michael Goulet Date: Fri Sep 22 17:59:52 2023 +0000 Fix debug printing of tuple commit 7e46fb9a658ceb5120fdf0de8665e7cc19114d7f Author: Mick van Gelderen Date: Fri Sep 22 19:41:00 2023 +0200 Fix large_futures example The value used in the large_futures example was not large enough to trigger the lint given the default threshold. The example also contained more code than necessary. This PR changes the value size from 1kB to 16kB and reduces the example in size. commit 2ba911c8329a4a8b6697cc6a25c02f0f06d58d8d Author: Oli Scherer Date: Fri Sep 22 16:26:20 2023 +0000 Have a single struct for queries and hook commit 9090ed8119871980a0fc9b9ea292f9eadf7a3c02 Author: Tomasz Miąsko Date: Thu Sep 21 00:00:00 2023 +0000 Fix test on targets with crt-static default commit 9f4e7c69456d56d1ec5ae18a82b816135e0dcdf4 Author: Oli Scherer Date: Tue Aug 8 07:23:16 2023 +0000 Bump ui_test crate commit e7063679414915d6eb70905b53723a3c21f3a141 Author: Oli Scherer Date: Fri Aug 4 11:26:55 2023 +0000 Allow limiting the number of threads running in parallel commit 0d5f51c290070335efa228c301d7ed5412a248ed Author: Oli Scherer Date: Fri Aug 4 11:22:06 2023 +0000 Bump ui_test crate commit c69e0c2a9bb652ea425da3546159a19255f11381 Author: Oli Scherer Date: Thu Aug 3 18:45:04 2023 +0000 Move `fail` tests that need dependencies into their own folder, so that wasm tests don't build dependencies commit 32c2ed7b263e649236561219ae2f781e8fa40c19 Author: Oli Scherer Date: Mon Jul 31 08:04:29 2023 +0000 Bump ui test crate commit 5db9a5ee3856a389215e2dc8cc9aa9d431b0b65a Author: Weihang Lo Date: Sat Sep 23 00:08:17 2023 +0800 Update cargo commit ab51f66ec087bfa0159ae19c699cb65049e48efa Author: pc-linux Date: Fri Sep 22 18:04:57 2023 +0200 added tests commit 861448b426d2cc62a4f62cf173591f9bc7a6c7a3 Author: ouz-a Date: Fri Sep 22 13:31:26 2023 +0300 make unsized cast illegal commit 959b2c703d45f06962da3afa086bdda70d42efcf Merge: 01903944d8c c4ec12f4b70 Author: bors Date: Fri Sep 22 15:19:38 2023 +0000 Auto merge of #115696 - RalfJung:closure-ty-print, r=oli-obk adjust how closure/generator types are printed I saw `&[closure@$DIR/issue-20862.rs:2:5]` and I thought it is a slice type, because that's usually what `&[_]` is... it took me a while to realize that this is just a confusing printer and actually there's no slice. Let's use something that cannot be mistaken for a regular type. commit 835d7d923b7a7234490fba5a0820eff2de1a60d3 Merge: 84917c83a85 1fac304bf53 Author: bors Date: Fri Sep 22 15:19:38 2023 +0000 Auto merge of #115696 - RalfJung:closure-ty-print, r=oli-obk adjust how closure/generator types are printed I saw `&[closure@$DIR/issue-20862.rs:2:5]` and I thought it is a slice type, because that's usually what `&[_]` is... it took me a while to realize that this is just a confusing printer and actually there's no slice. Let's use something that cannot be mistaken for a regular type. commit f3a27d20f60a7b0f23b9256ef6f405c4da8106fd Author: jonboh Date: Fri Sep 22 17:18:49 2023 +0200 prevent ice when threshold is 0 and enum has no variants commit 85801f55eff002a63db51125e9bc20aab1d4982e Author: pc-linux Date: Fri Sep 22 16:54:21 2023 +0200 fixed fp caused by moving &mut reference inside of a closure commit 1b34f1c6b2b407c286f0e0bac084114c7475c61e Author: Federico Stra Date: Mon Sep 18 19:27:26 2023 +0200 isqrt: add tests commit 3e8676c327086e4761674060793dcfd2f03d0c48 Author: Federico Stra Date: Mon Sep 18 18:34:44 2023 +0200 isqrt: initial implementation commit 17dfabff9c1d9dc34a07a7e4a8d18186d303a205 Author: Eduardo Sánchez Muñoz Date: Fri Sep 22 15:58:43 2023 +0200 Change `start` to `#[start]` in some diagnosis They refer to a function with the `start` attribute, but not necessarily named `start`. commit 8e06b25e3900b8b14d9043ff6d2b846199672b2b Author: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri Sep 22 15:31:19 2023 +0200 Remove TaKO8Ki from reviewers commit 63df126f59622f280dd34489eb7b3a03bdd7417d Author: ouz-a Date: Fri Sep 22 16:28:45 2023 +0300 match array for constantindex and subslice commit d4ffb3b08aa11e3b012e7efc31b28b78e01ed4bc Author: Matthew Jasper Date: Wed Sep 20 11:57:00 2023 +0000 Capture scrutinee of if let guards correctly Previously we were always capturing by value. commit 01903944d8c7e3cfdba88c9c7dbc09475b37d986 Merge: 03c199af8e0 3dd0419ea98 Author: bors Date: Fri Sep 22 13:01:30 2023 +0000 Auto merge of #115690 - ShE3py:Z-treat-err-as-bug, r=petrochenkov Allow `-Z treat-err-as-bug=0` Makes `-Z treat-err-as-bug=0` behave as if the option wasn't present instead of asking the value to be ⩾ 1. This enables a quick on/off of the option, as you only need to change one character instead of removing the whole `-Z`. Also update some text, e.g. ```bash $ rustc -Z help | grep treat-err-as-bug -Z treat-err-as-bug=val -- treat error number `val` that occurs as bug ``` where the value could be interpreted as an error code instead of an ordinal. commit c7e5f3ca085c3adfd285a6d41080ff65a6299bc9 Author: Ayush Singh Date: Sun May 21 14:26:59 2023 +0530 Rebase to master - Update Example - Add thread_parking to sys::uefi - Fix unsafe in unsafe errors - Improve docs - Improve os/exit - Some asserts - Switch back to atomics Signed-off-by: Ayush Singh commit 40c3dacc767a4fbf42ea5dfa686a54acf9ded5fb Author: Ayush Singh Date: Thu May 11 11:35:15 2023 +0530 Use RawOsError for UEFI Some changes from this commit will probably be converted to its own PR. Signed-off-by: Ayush Singh commit 7a956441a15e6056448233d79f2d03581ce0ccfc Author: Ayush Singh Date: Tue Mar 28 20:14:33 2023 +0530 Fixes from PR - Some comment fixes. - Make some functions unsafe. - Make helpers module private. - Rebase on master - Update r-efi to v4.2.0 Signed-off-by: Ayush Singh commit 5df24d18b6cdb8abcede6b658cf066360a219c12 Author: Ayush Singh Date: Mon Mar 27 19:53:53 2023 +0530 Add support for building `std::os::uefi` docs Signed-off-by: Ayush Singh commit 032e3766d54fe1b91ed13ff12652f91354d019cb Author: Ayush Singh Date: Sat Mar 25 14:20:49 2023 +0530 Handle ExitBootServices - Make BootServices unavailable if ExitBootServices event is signaled. - Use thread locals for SystemTable and ImageHandle Signed-off-by: Ayush Singh commit 8e56b33d59593a99fdef6f73f0c1a09a012ca907 Author: Ayush Singh Date: Sat Jan 28 23:37:54 2023 +0530 Fixes from PR Signed-off-by: Ayush Singh commit 48c6ae0611ec6fb4094a24610982ddefde16e20f Author: Ayush Singh Date: Sun Dec 18 09:54:54 2022 +0530 Add Minimal Std implementation for UEFI Implemented modules: 1. alloc 2. os_str 3. env 4. math Tracking Issue: https://github.com/rust-lang/rust/issues/100499 API Change Proposal: https://github.com/rust-lang/libs-team/issues/87 This was originally part of https://github.com/rust-lang/rust/pull/100316. Since that PR was becoming too unwieldy and cluttered, and with suggestion from @dvdhrm, I have extracted a minimal std implementation to this PR. Signed-off-by: Ayush Singh commit 3dd0419ea98da4d852c0aecec32eef0b466c07a6 Author: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Fri Sep 22 13:33:55 2023 +0200 Allow `-Z treat-err-as-bug=0` Co-authored-by: Vadim Petrochenkov commit 813fed2904fde5d5238e89e2e87fc9830b39a67d Author: Ralf Jung Date: Fri Sep 22 13:18:46 2023 +0200 fix OS-specific I/O safety docs since the io_safety feature is stable commit 03c199af8e0f10c4fe4ead8e97e65286bef86e7d Merge: 5a4e47ebedb 1a18ec0dcf8 Author: bors Date: Fri Sep 22 10:34:45 2023 +0000 Auto merge of #116054 - matthiaskrgr:rollup-3pusno6, r=matthiaskrgr Rollup of 7 pull requests Successful merges: - #114379 (Command: also print removed env vars) - #116034 (add UI test for delimiter errors) - #116036 (tests/ui: Split large_moves.rs and move to lint/large_assignments) - #116038 (Fall back to _SC_NPROCESSORS_ONLN if sched_getaffinity returns an empty mask) - #116039 (Account for nested `impl Trait` in TAIT) - #116041 (Add note to `is_known_rigid`) - #116049 (give FutureIncompatibilityReason variants more explicit names) r? `@ghost` `@rustbot` modify labels: rollup commit 1a18ec0dcf88f35b4682e7f630cbd3b167b56e92 Merge: 66f272d6ca9 7abbb9a4ffb Author: Matthias Krüger Date: Fri Sep 22 12:15:28 2023 +0200 Rollup merge of #116049 - RalfJung:future-incompat, r=Nilstrieb give FutureIncompatibilityReason variants more explicit names Also make the `reason` field mandatory when declaring a lint, to make sure this is a deliberate decision. commit 66f272d6ca9faf897a8cd668f2b0c9ce42ec507d Merge: fc4cfe01f6b 7fc081b4d96 Author: Matthias Krüger Date: Fri Sep 22 12:15:28 2023 +0200 Rollup merge of #116041 - compiler-errors:rigid-note, r=RalfJung Add note to `is_known_rigid` Adds a note requested by `@RalfJung` in https://github.com/rust-lang/rust/pull/114941#discussion_r1329963704 Let me know if there are any other fns that need documentation, I could throw them into this PR too :) commit fc4cfe01f6b0f0117e285b1349be17ff393bbcd4 Merge: faf13dd112b f2ede49c2f9 Author: Matthias Krüger Date: Fri Sep 22 12:15:27 2023 +0200 Rollup merge of #116039 - estebank:nested-tait, r=compiler-errors Account for nested `impl Trait` in TAIT Fix #116031. r? `@compiler-errors` commit faf13dd112bf0f455e5311cb1acc9db514defe78 Merge: 06608c78603 31cfa4a9561 Author: Matthias Krüger Date: Fri Sep 22 12:15:27 2023 +0200 Rollup merge of #116038 - the8472:panic-on-sched_getaffinity-bug, r=cuviper Fall back to _SC_NPROCESSORS_ONLN if sched_getaffinity returns an empty mask Followup to #115946 A gentler fix for #115868, one that doesn't panic, [suggested on zulip](https://rust-lang.zulipchat.com/#narrow/stream/259402-t-libs.2Fmeetings/topic/Meeting.202023-09-19/near/391942927) In that situation - on the buggy kernel versions - a zero-mask means no affinities have been set so `_SC_NPROCESSORS_ONLN` provides the right value. commit 06608c7860358eb995da112cbbf66f751feddc18 Merge: d5e7df3dbf6 d016e9a6860 Author: Matthias Krüger Date: Fri Sep 22 12:15:26 2023 +0200 Rollup merge of #116036 - Enselic:split-large_moves, r=oli-obk tests/ui: Split large_moves.rs and move to lint/large_assignments To make failing tests easier to debug with `--emit=mir`, etc. Don't bother with `revisions: attribute option` for both tests though. Seems sufficient to just have that on one of the tests. `git show -M --find-renames=40%` makes the diff easier to review. Or note that before this change we had one test with 4 errors, now we have 2 tests with 2 errors each. r? `@oli-obk` Part of https://github.com/rust-lang/rust/issues/83518 commit d5e7df3dbf61f5ecfa55b6f2d505c028a443b525 Merge: 9887dfab2c7 f7cd892b5af Author: Matthias Krüger Date: Fri Sep 22 12:15:26 2023 +0200 Rollup merge of #116034 - chenyukang:yukang-98601-add-ui-testcase, r=estebank add UI test for delimiter errors Fixes #98601 from https://github.com/rust-lang/rust/issues/98601#issuecomment-1721515067 r? `@estebank` commit 9887dfab2c7a204fafa2c1af6de5fd304f587322 Merge: 8759de0a493 98c94ec72f5 Author: Matthias Krüger Date: Fri Sep 22 12:15:25 2023 +0200 Rollup merge of #114379 - RalfJung:command-removed-env-vars, r=m-ou-se Command: also print removed env vars There is no real shell syntax for unsetting an env var so easily, so we have to make one up. But we already do that for showing the 'program' name so I hope that's okay here, too. No strong opinion on what that should look like, I went with `unset(VAR_NAME)` for now. commit 9defc971f1e059e139e8719661560de4741a128e Author: Oli Scherer Date: Fri Sep 22 09:25:38 2023 +0000 Add tracing instrumentation, just like queries automatically add it commit 5ee167e00d0c0563976239416ec344e7914455bd Author: Oli Scherer Date: Fri Sep 22 09:14:39 2023 +0000 Add a way to decouple the implementation and the declaration of a TyCtxt method. commit 2157f3173161dae18621ccdfb88a1446eb2d41ff Author: Oli Scherer Date: Fri Sep 22 09:14:39 2023 +0000 Add a way to decouple the implementation and the declaration of a TyCtxt method. commit 5a4e47ebedb4132168c1b22262f21f0d3a2a96df Merge: 8759de0a493 1290cd432dd Author: bors Date: Fri Sep 22 08:47:51 2023 +0000 Auto merge of #114780 - RalfJung:io-safety, r=Amanieu add more explicit I/O safety documentation Fixes https://github.com/rust-lang/unsafe-code-guidelines/issues/434 Cc https://github.com/rust-lang/rust/issues/114167 Cc `@Manishearth` `@sunfishcode` `@joshtriplett` commit 7abbb9a4ffb17af4fea40222264ed87c736310e6 Author: Ralf Jung Date: Fri Sep 22 10:37:05 2023 +0200 hide rustc line numbers in test commit ce33ca0a1e5d10589fa6ea89ef64242b1b6552dc Merge: aea1eff871c 896065f9026 Author: bors Date: Fri Sep 22 08:36:18 2023 +0000 Auto merge of #3074 - rust-lang:rustup-2023-09-22, r=RalfJung Automatic sync from rustc commit 896065f902602e99c6996cee9cee99ab7c00dcaa Author: Ralf Jung Date: Fri Sep 22 10:35:58 2023 +0200 clippy commit 442c87a0b0168e644a40ef8ecd874c53fe7e04b8 Author: ouz-a Date: Fri Sep 22 11:31:14 2023 +0300 better bug message commit d6efedcaf578e67f07293349d2128c06043a239f Author: ouz-a Date: Fri Sep 22 11:21:55 2023 +0300 remove inner match commit ec188115578db5207ba84977d7314a58e7d117e1 Author: Ralf Jung Date: Thu Sep 21 13:58:24 2023 +0200 run abi/compatibility test against a whole bunch of targets commit 8759de0a4935e677fdce99a849addea2d5318da9 Merge: aace2dfa37f ab168b6ef3b Author: bors Date: Fri Sep 22 07:00:52 2023 +0000 Auto merge of #114776 - fee1-dead-contrib:enable-effects-in-libcore, r=oli-obk Enable effects for libcore ~~r? `@oli-obk~~` forgot you are on vacation, oops commit 84917c83a85444a06bd4a11ac81541e453f762c7 Merge: 823bcb478bc 74573fbab98 Author: bors Date: Fri Sep 22 07:00:52 2023 +0000 Auto merge of #114776 - fee1-dead-contrib:enable-effects-in-libcore, r=oli-obk Enable effects for libcore ~~r? `@oli-obk~~` forgot you are on vacation, oops commit 5586c2a68f2b6b9b09d025ad52df7ba288852222 Author: Ralf Jung Date: Fri Sep 22 08:59:32 2023 +0200 make the reason: field mandatory for @future_incompatible lints commit e888d470e91ee4e027871d850766802a6b6dad86 Author: Ralf Jung Date: Fri Sep 22 08:25:11 2023 +0200 give FutureIncompatibilityReason variants more explicit names commit e6a4a1b12e0d8df98d80c1f4f4c3b09b9b994257 Author: The Miri Conjob Bot Date: Fri Sep 22 05:40:22 2023 +0000 fmt commit bf31cdb08ae233a147437251b7ecc366284d1209 Merge: 5211d045c9a d5ec9af09da Author: The Miri Conjob Bot Date: Fri Sep 22 05:37:52 2023 +0000 Merge from rustc commit 5211d045c9aa105cd241106183366da5e6d6416c Author: The Miri Conjob Bot Date: Fri Sep 22 05:29:34 2023 +0000 Preparing for merge from rustc commit aea1eff871cdb587e936613a9b3d160cd5d61049 Merge: 5b8695b6bcb 838e6a6b78e Author: bors Date: Fri Sep 22 05:29:32 2023 +0000 Auto merge of #3073 - RalfJung:cron, r=RalfJung run the cron job a bit earlier commit 838e6a6b78ec61c2802d8f1364d2f07c4e2453db Author: Ralf Jung Date: Fri Sep 22 07:28:56 2023 +0200 run the cron job a bit earlier commit aace2dfa37f4589b0071530d2ed7b352f6196704 Merge: b7573187180 9102816bc4d Author: bors Date: Fri Sep 22 05:07:45 2023 +0000 Auto merge of #115910 - eduardosm:lang-fns-target-features, r=cjgillot Prevent using `#[target_feature]` on lang item functions Fixes https://github.com/rust-lang/rust/issues/109411 and also prevents from using `#[target_feature]` on other `fn` lang items to mitigate the concerns from https://github.com/rust-lang/rust/issues/109411#issuecomment-1477030273. commit d5ec9af09da9f6d96b350ee53fffdad58721d32e Author: Arthur Lafrance Date: Thu Sep 21 20:42:21 2023 -0700 Add test to guard against VecDeque optimization regression commit 7fc081b4d96dc2f5cc4e291569a14e9b7f6461aa Author: Michael Goulet Date: Thu Sep 21 19:05:09 2023 +0000 Add note to is_known_rigid commit b7573187180a6ad13ba557f85b7e19a51f8fdaf1 Merge: 99b63d068b0 1806efe7f27 Author: bors Date: Fri Sep 22 00:46:13 2023 +0000 Auto merge of #115920 - Zoxc:depkind-u16, r=cjgillot Move `DepKind` to `rustc_query_system` and define it as `u16` This moves the `DepKind` type to `rustc_query_system` where it's defined with an inner `u16` field. This decouples it from `rustc_middle` and is a step towards letting other crates define dep kinds. It also allows some type parameters to be removed. The `DepKind` trait is replaced with a `Deps` trait. That's used when some operations or information about dep kinds which is unavailable in `rustc_query_system` are still needed. r? `@cjgillot` commit 3799af3337d748647ca6c4abbad63975275a7a37 Author: Michael Howell Date: Thu Sep 21 17:14:58 2023 -0700 diagnostics: avoid mismatch between variance index and hir generic This happens because variances are constructed from ty generics, and ty generics are always constructed with lifetimes first. See compiler/rustc_hir_analysis/src/collect/generics_of.rs:248-269 Fixes #83556 commit ab168b6ef3b276d06fdf0aac236b9881841815ed Author: Deadbeef Date: Fri Sep 22 00:05:45 2023 +0000 fix clippy errors (ignore effects in certainty) commit 74573fbab98fe3eeaef63ada418613bff0a77c62 Author: Deadbeef Date: Fri Sep 22 00:05:45 2023 +0000 fix clippy errors (ignore effects in certainty) commit 99b63d068b0be31b4d8a28f93921b5d14f13cdc0 Merge: b3aa8e7168a 85d61b01aea Author: bors Date: Thu Sep 21 22:59:13 2023 +0000 Auto merge of #115897 - eduardosm:check-fn-sig, r=compiler-errors rustc_hir_analysis: add a helper to check function the signature mismatches This function is now used to check `#[panic_handler]`, `start` lang item, `main`, `#[start]` and intrinsic functions. The diagnosis produced are now closer to the ones produced by trait/impl method signature mismatch. This is the first time I do anything with rustc_hir_analysis/rustc_hir_typeck, so comments and suggestions about things I did wrong or that could be improved will be appreciated. commit b3aa8e7168a3d940122db3561289ffbf3f587262 Merge: f73d376fb66 9072415252d Author: bors Date: Thu Sep 21 21:12:32 2023 +0000 Auto merge of #115864 - compiler-errors:rpitit-sugg, r=estebank Suggest desugaring to return-position `impl Future` when an `async fn` in trait fails an auto trait bound First commit allows us to store the span of the `async` keyword in HIR. Second commit implements a suggestion to desugar an `async fn` to a return-position `impl Future` in trait to slightly improve the `Send` situation being discussed in #115822. This suggestion is only made when `#![feature(return_type_notation)]` is not enabled -- if it is, we should instead suggest an appropriate where-clause bound. commit c4ec12f4b701d9be95143f3fa77b1f1af07de18c Author: Ralf Jung Date: Sat Sep 9 08:36:50 2023 +0200 adjust how closure/generator types and rvalues are printed commit 1fac304bf53f35f2088fad9b40cd919cd7a485d9 Author: Ralf Jung Date: Sat Sep 9 08:36:50 2023 +0200 adjust how closure/generator types and rvalues are printed commit f73d376fb669859b167cb04121c52f7f6f71a05e Merge: 24b45c3bdcd dcea7709f2c Author: bors Date: Thu Sep 21 19:24:01 2023 +0000 Auto merge of #115230 - Vtewari2311:mod-hurd-latest, r=b-naber added support for GNU/Hurd adding support for i686-unknown-hurd-gnu commit 823bcb478bc55cacee0dcc1a9cc2b70decfa1d39 Author: Michael Goulet Date: Thu Sep 14 22:38:07 2023 +0000 Record asyncness span in HIR commit 9072415252d6dde7f23acc21a6781f27c703ac9d Author: Michael Goulet Date: Fri Sep 15 05:00:39 2023 +0000 Suggest desugaring to RPITIT when AFIT is required to be an auto trait commit 087a571e708560bad84b1dd8de107c8fdc2a3044 Author: Michael Goulet Date: Thu Sep 14 22:38:07 2023 +0000 Record asyncness span in HIR commit d016e9a68602199bc4bb7c6e4f00a31c7284b3d4 Author: Martin Nordholts Date: Thu Sep 21 18:28:08 2023 +0200 tests/ui: Split large_moves.rs and move to lint/large_assignments To make failing tests easier to debug with --emit=mir, etc. commit 31cfa4a95611b1151bcdee213d39e2edbeee6c19 Author: The 8472 Date: Thu Sep 21 19:29:36 2023 +0200 Fall back to _SC_NPROCESSORS_ONLN if sched_getaffinity returns an empty mask commit f2ede49c2f9da8c64782abbec3b4a1710d52a4c5 Author: Esteban Küber Date: Thu Sep 21 17:47:09 2023 +0000 Account for nested `impl Trait` in TAIT Fix #116031. commit 24b45c3bdcd7435d57d222d1d47cb4ab2cf114d1 Merge: 0fd7ce99b05 041a232b62d Author: bors Date: Thu Sep 21 17:29:30 2023 +0000 Auto merge of #114399 - Zalathar:no-renumber, r=jackh726 coverage: Don't bother renumbering expressions on the Rust side The LLVM API that we use to encode coverage mappings already has its own code for removing unused coverage expressions and renumbering the rest. This lets us get rid of our own complex renumbering code, making it easier to change our coverage code in other ways. --- Now that we have tests for coverage mappings (#114843), I've been able to verify that this PR doesn't make the coverage mappings worse, thanks to an explicit simplification step. commit afdd468ab8f4b028ef2eb024b9f724e2feeac72f Author: Martin Nordholts Date: Thu Sep 21 18:25:13 2023 +0200 tests/ui: Fix large_moves attribute cfg We only want the attribute for the attribute revision. commit b075a9d2ab491b921d3ecdd4d25f65d923bb6cd3 Author: Eduardo Sánchez Muñoz Date: Thu Sep 21 18:25:41 2023 +0200 Implement `llvm.ctpop.v*` intrinsics Tested through x86 avx512vpopcntdq and avx512bitalg functions. commit 5b8695b6bcbb90b6e92fe748eaa822eedf1c5c00 Merge: d2db689e1ef 64708fbf9ef Author: bors Date: Thu Sep 21 15:40:16 2023 +0000 Auto merge of #3071 - RalfJung:deprecate-disable-abi, r=oli-obk,saethlin deprecate -Zmiri-disable-abi-check This was added in https://github.com/rust-lang/miri/pull/1776 but I couldn't find any discussion or motivation. commit dcea7709f2ce1be35ba241e923850b1099ceb906 Author: Samuel Thibault Date: Tue Sep 19 12:41:30 2023 +0200 added support for GNU/Hurd commit 33f084ef78f1424241c59a69959d5a7bad0e4700 Merge: 4d143d7e16c 01c25a8eb63 Author: bors Date: Thu Sep 21 15:25:36 2023 +0000 Auto merge of #11544 - Alexendoo:hir-ty-to-ty, r=Jarcho Remove most usage of `hir_ty_to_ty` Removes the usages where there's a suitable query or the type was already available elsewhere. The remaining cases would all require more involved changes changelog: none r? `@Jarcho` commit f7cd892b5af65069bfff5ab1e37210abb737877e Author: yukang Date: Thu Sep 21 22:56:17 2023 +0800 add UI test for delimiter errors commit 1806efe7f2757c5fbcf99d1ac9ca2d26fb0a7c4e Author: John Kåre Alsaker Date: Fri Sep 15 15:39:11 2023 +0200 Move `DepKind` to `rustc_query_system` and define it as `u16` commit 8071ec78eacb843cab0db927df87cecae6926ba5 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed Sep 20 18:30:06 2023 +0000 Always explicitly set the preserve_frame_pointers value commit 0fd7ce99b0508aff7f7a2c639871de4e8080e3f8 Merge: 66ab7e6883c 0eff07b748b Author: bors Date: Thu Sep 21 14:02:55 2023 +0000 Auto merge of #116010 - RalfJung:more-typed-immediates, r=oli-obk interpret: more consistently use ImmTy in operators and casts The diff in src/tools/miri/src/shims/x86/sse2.rs should hopefully suffice to explain why this is nicer. :) commit 02dec62de5e1455bd0a382f840c52409f26b7185 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 21 13:32:55 2023 +0000 Update to Cranelift 0.100 This skips Cranelift 0.99 as it depends on an object version that is broken on macOS. commit 4d143d7e16c05bebe569374f277bdf5ef8667e07 Merge: c55669513af 5b790ff9e0e Author: bors Date: Thu Sep 21 12:27:24 2023 +0000 Auto merge of #11518 - mojave2:issue-11420, r=Alexendoo fix FP with needless_raw_string_hashes changelog: Fix [`needless_raw_string_hashes`]: Continue the lint checking of raw string when `needless_raw_strings` is allowed. fix #11420 commit 66ab7e6883c563ceacf8386a50e851e9855cd6b4 Merge: e4a361a48a5 e9aee820b31 Author: bors Date: Thu Sep 21 12:04:33 2023 +0000 Auto merge of #116027 - GuillaumeGomez:rollup-3zdi9lf, r=GuillaumeGomez Rollup of 5 pull requests Successful merges: - #115257 (Improve invalid UTF-8 lint by finding the expression initializer) - #115936 (Prevent promotion of const fn calls in inline consts) - #115972 (rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const) - #116007 (Call panic_display directly in const_panic_fmt.) - #116019 (Delete obsolete `--disable-per-crate-search` rustdoc flag) r? `@ghost` `@rustbot` modify labels: rollup commit e9aee820b310e82c7c86ecd7fd931c6f3c51350f Merge: 0d2c603b12a 3dcc8fcab5e Author: Guillaume Gomez Date: Thu Sep 21 13:25:40 2023 +0200 Rollup merge of #116019 - dtolnay:percratesearch, r=GuillaumeGomez Delete obsolete `--disable-per-crate-search` rustdoc flag This unstable flag is unused by rustdoc since https://github.com/rust-lang/rust/pull/92526/commits/ef96d573bff12330080d22f12cad96b818ea5da7. We should avoid landing this until after https://github.com/rust-lang/docs.rs/pull/2225 is deployed to docs.rs. commit 0d2c603b12a5e9bedbde452f203355a3f66efab6 Merge: 208f6ed95cb 667bba46b0d Author: Guillaume Gomez Date: Thu Sep 21 13:25:40 2023 +0200 Rollup merge of #116007 - m-ou-se:const-panic-fmt-panic-display, r=oli-obk Call panic_display directly in const_panic_fmt. `panic_str` just directly calls `panic_display`. The only reason `panic_str` exists, is for a lint to detect an expansion of `panic_2015!(expr)` (which expands to `panic_str`). It is `panic_display` that is hooked by const-eval, which is the reason we call it here. Part of https://github.com/rust-lang/rust/issues/116005 r? ``@oli-obk`` commit 1351de36eebd2304b8905b0e29138f04ed49bb41 Merge: dd48b5e3938 0e02cab8ba8 Author: Guillaume Gomez Date: Thu Sep 21 13:25:39 2023 +0200 Rollup merge of #115972 - RalfJung:const-consistency, r=oli-obk rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const Also, be more consistent with the `to/eval_bits` methods... we had some that take a type and some that take a size, and then sometimes the one that takes a type is called `bits_for_ty`. Turns out that `ty::Const`/`mir::ConstKind` carry their type with them, so we don't need to even pass the type to those `eval_bits` functions at all. However this is not properly consistent yet: in `ty` we have most of the methods on `ty::Const`, but in `mir` we have them on `mir::ConstKind`. And indeed those two types are the ones that correspond to each other. So `mir::ConstantKind` should actually be renamed to `mir::Const`. But what to do with `mir::Constant`? It carries around a span, that's really more like a constant operand that appears as a MIR operand... it's more suited for `syntax.rs` than `consts.rs`, but the bigger question is, which name should it get if we want to align the `mir` and `ty` types? `ConstOperand`? `ConstOp`? `Literal`? It's not a literal but it has a field called `literal` so it would at least be consistently wrong-ish... ``@oli-obk`` any ideas? commit 12815e95f99fe17f1782eeffd4159738c730d1c4 Merge: 238dc2828ed 2ea6ac56739 Author: Guillaume Gomez Date: Thu Sep 21 13:25:39 2023 +0200 Rollup merge of #115972 - RalfJung:const-consistency, r=oli-obk rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const Also, be more consistent with the `to/eval_bits` methods... we had some that take a type and some that take a size, and then sometimes the one that takes a type is called `bits_for_ty`. Turns out that `ty::Const`/`mir::ConstKind` carry their type with them, so we don't need to even pass the type to those `eval_bits` functions at all. However this is not properly consistent yet: in `ty` we have most of the methods on `ty::Const`, but in `mir` we have them on `mir::ConstKind`. And indeed those two types are the ones that correspond to each other. So `mir::ConstantKind` should actually be renamed to `mir::Const`. But what to do with `mir::Constant`? It carries around a span, that's really more like a constant operand that appears as a MIR operand... it's more suited for `syntax.rs` than `consts.rs`, but the bigger question is, which name should it get if we want to align the `mir` and `ty` types? `ConstOperand`? `ConstOp`? `Literal`? It's not a literal but it has a field called `literal` so it would at least be consistently wrong-ish... ``@oli-obk`` any ideas? commit 208f6ed95cbca95a0a4f28dd6a72524f1734a533 Merge: d05c5fecdec c94410c1458 Author: Guillaume Gomez Date: Thu Sep 21 13:25:39 2023 +0200 Rollup merge of #115972 - RalfJung:const-consistency, r=oli-obk rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const Also, be more consistent with the `to/eval_bits` methods... we had some that take a type and some that take a size, and then sometimes the one that takes a type is called `bits_for_ty`. Turns out that `ty::Const`/`mir::ConstKind` carry their type with them, so we don't need to even pass the type to those `eval_bits` functions at all. However this is not properly consistent yet: in `ty` we have most of the methods on `ty::Const`, but in `mir` we have them on `mir::ConstKind`. And indeed those two types are the ones that correspond to each other. So `mir::ConstantKind` should actually be renamed to `mir::Const`. But what to do with `mir::Constant`? It carries around a span, that's really more like a constant operand that appears as a MIR operand... it's more suited for `syntax.rs` than `consts.rs`, but the bigger question is, which name should it get if we want to align the `mir` and `ty` types? `ConstOperand`? `ConstOp`? `Literal`? It's not a literal but it has a field called `literal` so it would at least be consistently wrong-ish... ``@oli-obk`` any ideas? commit d05c5fecdec41d40ebf04a686b27019326525cb4 Merge: 9ce64bae941 9c762b58ba9 Author: Guillaume Gomez Date: Thu Sep 21 13:25:38 2023 +0200 Rollup merge of #115936 - oli-obk:inline_const_promotion, r=RalfJung Prevent promotion of const fn calls in inline consts We don't wanna make that mistake we did for statics and consts worse by letting more code use it. r? ``@RalfJung`` cc https://github.com/rust-lang/rust/issues/76001 commit 9ce64bae9415d0680f89137d705a06629b29fcae Merge: e4a361a48a5 f156d3bc572 Author: Guillaume Gomez Date: Thu Sep 21 13:25:38 2023 +0200 Rollup merge of #115257 - Urgau:invalid-utf8-walk-up-hir, r=Nilstrieb Improve invalid UTF-8 lint by finding the expression initializer This PR introduce a small mechanism to walk up the HIR through bindings, if/else, consts, ... when trying lint on invalid UTF-8. Fixes https://github.com/rust-lang/rust/issues/115208 commit 34c248d31f8351e33e597abcea2a3bffff653a4d Author: Tomasz Miąsko Date: Sun Sep 10 00:00:00 2023 +0000 compiletest: load supports-xray from target spec commit 64e27cb4d9eb41928ca959a616e06d2e9c4c3fdb Author: Tomasz Miąsko Date: Sat Sep 9 00:00:00 2023 +0000 compiletest: load supported sanitizers from target spec commit bc7bb3c8e7f62a490055cfd2aa43b6dc77c0f3f7 Author: Tomasz Miąsko Date: Sat Sep 9 00:00:00 2023 +0000 compiletest: use builder pattern to construct Config in tests commit 238dc2828ed4b2ce49a95b8093486cd01c528af9 Author: Oli Scherer Date: Mon Sep 18 15:30:07 2023 +0000 Prevent promotion of const fn calls in inline consts commit 9c762b58ba9f46e806f7e07b80ef59b45de87471 Author: Oli Scherer Date: Mon Sep 18 15:30:07 2023 +0000 Prevent promotion of const fn calls in inline consts commit 44e199bf300a79df302a5b068dba0c39d9a12c0f Author: Oli Scherer Date: Mon Sep 18 15:20:36 2023 +0000 Add regression test commit 041a232b62dba833a4cfdca3f74e4029b53200a0 Author: Zalathar Date: Sun Jul 23 11:48:31 2023 +1000 coverage: Don't bother renumbering expressions on the Rust side The LLVM API that we use to encode coverage mappings already has its own code for removing unused coverage expressions and renumbering the rest. This lets us get rid of our own complex renumbering code, making it easier to change our coverage code in other ways. commit 527c629cd9d2cc689eabb99d4e246b01401f2564 Author: Zalathar Date: Mon Aug 14 18:01:28 2023 +1000 coverage: Explicitly simplify coverage expressions in codegen After coverage instrumentation and MIR transformations, we can sometimes end up with coverage expressions that always have a value of zero. Any expression operand that refers to an always-zero expression can be replaced with a literal `Operand::Zero`, making the emitted coverage mapping data smaller and simpler. This simplification step is mostly redundant with the simplifications performed inline in `expressions_with_regions`, except that it does a slightly more thorough job in some cases (because it checks for always-zero expressions *after* other simplifications). However, adding this simplification step will then let us greatly simplify that code, without affecting the quality of the emitted coverage maps. commit 659575aade611f19b8e75e39224781b1f6f15ee6 Author: Zalathar Date: Wed Aug 2 15:55:37 2023 +1000 coverage: Make the zero counter a constant commit f156d3bc5720603b8ce7a6a33bbfd464f9ca2e84 Author: Urgau Date: Sat Aug 26 22:09:18 2023 +0200 Improve invalid UTF-8 lint by finding the expression initializer commit d2db689e1efa5b3fff6b664b6d2dba0ef65b80e7 Merge: 70f3d3e6ad6 ed8fbcb0591 Author: bors Date: Thu Sep 21 08:01:45 2023 +0000 Auto merge of #3069 - rust-lang:rustup-2023-09-21, r=RalfJung Automatic sync from rustc commit e4a361a48a59ead52b302aaa2e1d9d345264935a Merge: 0a689c1be85 614760f612f Author: bors Date: Thu Sep 21 07:58:28 2023 +0000 Auto merge of #115996 - lcnr:intercrate_ambiguity_causes-uwu, r=compiler-errors implement `intercrate_ambiguity_causes` in the new solver I added some comments but this is still somewhat of a mess. I think we should for the most part be able to treat all of this as a black box, so I can accept that this code isn't too great. I also believe that some of the weirdness here is unavoidable, as proof trees - and their visitor - hide semantically relevant information, so they cannot perfectly represent the actual solver behavior. There are some known bugs here when testing with `./x.py test tests/ui --bless -- --target-rustcflags -Ztrait-solver=next-coherence`. While I haven't diagnosed them all in detail I believe we are able to handle them all separately - `structurally_normalize` currently does not normalize opaque types, resulting in divergence between the solver internal `trait_ref_is_knowable` and the one when computing intercrate ambiguity causes. - we don't add an `intercrate_ambiguity_cause` for reserved impls - we should `deeply_normalize` the trait ref before printing it, that requires a "best effort" version of `deeply_normalize` r? `@compiler-errors` commit 614760f612fa72ba9d6955c00624c592b884d28f Author: lcnr Date: Thu Sep 21 08:56:23 2023 +0200 review commit 8167a25e4e64920e3b02e6ed2342e5b6abc25e95 Author: lcnr Date: Thu Sep 21 08:44:12 2023 +0200 w commit 64708fbf9ef018e682ee9bb5716974f057e97129 Author: Ralf Jung Date: Thu Sep 21 07:57:38 2023 +0200 deprecate -Zmiri-disable-abi-check commit 8e139eefaf276108c56fda1ec0c7fb972ce8df0c Author: lcnr Date: Thu Sep 21 08:40:36 2023 +0200 slight refactor, add comment commit 6c73f254b977574a2e155dc18c4f96746071f4e0 Author: Ralf Jung Date: Thu Sep 21 08:31:16 2023 +0200 avoid talking about inverses commit 14625f5b3ec9730bef12c63f7d4fb4c43d118d7a Author: Ralf Jung Date: Sat Aug 19 16:44:54 2023 +0200 consistent wording commit 39b53dc204e944e37fef621d4799a561f423cfd3 Author: Ralf Jung Date: Mon Jul 31 14:24:11 2023 +0200 documentation tweaks commit 62bdb1a6e0011d6dbbcc552afebaffbd8fd26104 Author: Ralf Jung Date: Mon Jul 17 17:45:31 2023 +0200 offset_from: docs improvements commit 8024c69c2985274f8caf8bccdeec92a5632bd8c3 Author: lcnr Date: Wed Sep 20 21:41:29 2023 +0200 HACK: avoid hang in structurally_normalize commit 8eade3aa71fd3c08de4e8849a91ef9154e83a054 Author: lcnr Date: Wed Sep 20 21:41:19 2023 +0200 update tests commit de53877f8b52818458e12045d65d83df9970de10 Author: lcnr Date: Wed Sep 20 21:41:07 2023 +0200 proof trees: use for `intercrate_ambiguity_causes` commit 0e02cab8ba8d9b10ac258c071e7b1b9270e623d0 Author: Ralf Jung Date: Wed Sep 20 20:51:14 2023 +0200 rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const commit 2ea6ac5673931cd0804507ebe57452914d76f552 Author: Ralf Jung Date: Wed Sep 20 20:51:14 2023 +0200 rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const commit c94410c1458f9ea55e51fc9af478d94a82ec90a0 Author: Ralf Jung Date: Wed Sep 20 20:51:14 2023 +0200 rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const commit 70f3d3e6ad6656546f79fac961ed3a4316003fa3 Merge: 59105177cc9 a11b1d8b26f Author: bors Date: Thu Sep 21 06:06:36 2023 +0000 Auto merge of #3070 - RalfJung:no-no-merges, r=RalfJung disable no-merges check for now It leads to false warnings on sync PRs until https://github.com/rust-lang/triagebot/pull/1720 lands. commit ed8fbcb05910f4439ec572bd163cc99a3603e378 Author: Ralf Jung Date: Thu Sep 21 08:03:45 2023 +0200 fix clippy lints commit e018f49d4597cc5575703e3ff1d53a8cba11757a Author: Ralf Jung Date: Thu Sep 21 08:02:58 2023 +0200 remove atty dependency by updating colored commit a11b1d8b26f99b256b9e14cf540d8c457d6c83fe Author: Ralf Jung Date: Thu Sep 21 07:49:38 2023 +0200 disable no-merges check for now commit 96a85d67fd0e986ba8f9ee2207f3c916f46b4bb1 Author: Ralf Jung Date: Thu Sep 21 07:46:41 2023 +0200 update lockfile commit e6cd29d06e48186562eefe6007854ca9776e6e8f Author: The Miri Conjob Bot Date: Thu Sep 21 05:40:21 2023 +0000 fmt commit de5d1648b8b779f7778af04c4a7510c408861562 Merge: 4b865b7d1aa 9090ed81198 Author: The Miri Conjob Bot Date: Thu Sep 21 05:37:42 2023 +0000 Merge from rustc commit 4b865b7d1aa4ffe2e760adfdc9744d6a656ba96a Author: The Miri Conjob Bot Date: Thu Sep 21 05:28:08 2023 +0000 Preparing for merge from rustc commit 0eff07b748b82240cd9605c631268ba1c8c8e58f Author: Ralf Jung Date: Thu Sep 21 07:26:11 2023 +0200 try to avoid some layout_of calls commit 3dcc8fcab5eecf1cf9715ed78609994ec37c9863 Author: David Tolnay Date: Wed Sep 20 22:09:48 2023 -0700 Delete obsolete --disable-per-crate-search rustdoc flag commit d30f210e5d20e3a03a015f95324021fb711cfc58 Author: DianQK Date: Thu Sep 21 12:29:20 2023 +0800 Increasing the SIMD size improves the vectorization possibilities Change the simd-wide-sum.rs to pass the LLVM main branching test. commit c55669513af7e0afaf65bd9b150fd827dc4446c2 Merge: ddbe1100813 558ae4c6a8a Author: bors Date: Wed Sep 20 23:57:25 2023 +0000 Auto merge of #11522 - y21:redundant_guards_pat_lhs, r=giraffate [`redundant_guards`]: lint if the pattern is on the left side A tiny improvement to the `redundant_guards` lint. There's no associated issue for this, just noticed it while going through the code. Right now it warns on `Some(x) if x == 2` and suggests `Some(2)`, but it didn't do that for `Some(x) if 2 == x` (i.e. when the local is on the right side and the pattern on the left side). changelog: [`redundant_guards`]: also lint if the pattern is on the left side commit 667bba46b0dc1ed5f481431c48c24b8326e099a1 Author: Mara Bos Date: Wed Sep 20 22:37:39 2023 +0200 Fix typo. commit 23fd2860fa0aa521083019df952d762b43400212 Author: Ralf Jung Date: Wed Sep 20 22:28:46 2023 +0200 stronger consistency check in ImmTy::from_immediate commit bdbf545f4216bc316822610b7ab231d336ecec2b Author: Ralf Jung Date: Wed Sep 20 22:25:09 2023 +0200 interpret: less debug-printing of types commit da08a3f40c38b233a57aa0b9aca6c875ab383240 Author: Ralf Jung Date: Wed Sep 20 21:49:30 2023 +0200 interpret: more consistently use ImmTy in operators and casts commit b8c85207250cb90d658fd767137c4b63ecc43d01 Author: Camille GILLOT Date: Wed Sep 20 18:18:44 2023 +0000 Ignore debug-assertions in test. commit 0d07b4c2ce5bd677735dc8d2265395d52041636f Author: Mara Bos Date: Wed Sep 20 18:59:12 2023 +0200 Call panic_display directly in const_panic_fmt. commit 8d81d5a909551631b51177f976f68ac02dcafd11 Author: León Orell Valerian Liehr Date: Fri Aug 18 13:23:53 2023 +0200 Validate crate name in CLI option --extern commit e76b7f226aa5e463007b85767452cb9c561c418f Author: Camille GILLOT Date: Tue Sep 12 17:29:32 2023 +0000 Do not create a DerefLen place for `Box<[T]>`. commit 01c25a8eb63f8da0453d1aedca782f477342ef2d Author: Alex Macleod Date: Wed Sep 20 13:41:20 2023 +0000 Remove most usage of `hir_ty_to_ty` commit 42a033affa24f85768a7c13a527d417742713b65 Author: yukang Date: Wed Sep 20 19:08:04 2023 +0800 Cleanup unused messages in ftl files commit ddbe1100813d75898d6cde56a498813ac5799e9d Merge: ece3878c8cc 1b3e5dd0fca Author: bors Date: Wed Sep 20 08:06:54 2023 +0000 Auto merge of #11170 - tgross35:undocumented-unsafe-blocks-defaults, r=Centri3 Change defaults of `accept-comment-above-statement` and `accept-comment-above-attributes` This patch sets the two configuration options for `undocumented_unsafe_blocks` to `true` by default: these are `accept-comment-above-statement` and `accept-comment-above-attributes`. Having these values `false` by default prevents what many users would consider clean code, e.g. placing the `// SAFETY:` comment above a single-line functino call, rather than directly next to the argument. This was originally discussed in https://github.com/rust-lang/rust-clippy/issues/11162 changelog: [`undocumented_unsafe_blocks`]: set `accept-comment-above-statement` and `accept-comment-above-attributes` to `true` by default. commit 77e205a113e4843d1b84467afe8ea74a36ed9424 Author: Obei Sideg Date: Wed Sep 13 20:42:56 2023 +0300 Migrate `rustc_hir_analysis` to session diagnostic Part 5: Finishing `coherence/builtin.rs` file commit ece3878c8cc74da936d067ee25a4ccc959ea55dd Merge: f464149b8f3 b8b420cc79d Author: bors Date: Wed Sep 20 07:48:54 2023 +0000 Auto merge of #11492 - GuillaumeGomez:async-fn-returned-closure, r=Centri3 Fix mutaby used async function argument in closure for `needless_pass_by_ref_mut` Fixes https://github.com/rust-lang/rust-clippy/issues/11380. The problem was that it needed to go through closures as well in async functions to correctly find the mutable usage of async function arguments. changelog: Correctly handle mutable usage of async function arguments in closures. r? `@Centri3` commit 1b3e5dd0fcae6056e8ab435b795eb4d73f69230d Author: Trevor Gross Date: Mon Jul 17 00:30:24 2023 -0400 Change default configuration of `undocumented_unsafe_blocks` This patch sets the two configuration options for `undocumented_unsafe_blocks` to `true` by default: these are `accept-comment-above-statement` and `accept-comment-above-attributes`. Having these values `false` by default prevents what many users would consider clean code, e.g. placing the `// SAFETY:` comment above a single-line functino call, rather than directly next to the argument. changelog: [`undocumented_unsafe_blocks`]: set `accept-comment-above-statement` and `accept-comment-above-attributes` to `true` by default. commit a2374e65aafd47fa68a3954fa2a3116c519aa7e5 Author: Ralf Jung Date: Tue Sep 19 17:44:31 2023 +0200 the Const::eval_bits methods don't need to be given the Ty commit 2063ebc3eac2587612fea57c2e48e7b6a78f9736 Author: Deadbeef Date: Wed Sep 20 02:25:49 2023 +0000 bless the known-bug tests commit 7446012c1e6bcf9669684399337ede66072b41a3 Author: Deadbeef Date: Wed Sep 20 01:57:06 2023 +0000 fix rustdoc tests commit a3b5f1ad85828e15ceceedb8fdb950072e7d9776 Author: Deadbeef Date: Wed Sep 20 01:34:37 2023 +0000 ignore host effect params in rustdoc commit 7b1b17574bf1466ddd7e6657b6122244dc5a73ce Author: Deadbeef Date: Tue Sep 12 01:07:04 2023 +0000 fix bugs with effects fallback commit 04eec37dc2cababaecffd423e330d3c19d3c6169 Author: Deadbeef Date: Sun Aug 13 09:02:31 2023 +0000 Enable effects for libcore commit f464149b8f3e4d24139491a8f4049bc6eef0de38 Merge: 889e1b99bda 3cad6237166 Author: bors Date: Wed Sep 20 00:00:06 2023 +0000 Auto merge of #11516 - mojave2:issue-11458, r=giraffate fix cast_lossless with macro call changelog: fix [`cast_lossless`] in the case when the cast operand is a macro call fix #11458 commit 85d61b01aea90d9201c35c4bd61a508c72807c92 Author: Eduardo Sánchez Muñoz Date: Tue Sep 19 21:15:58 2023 +0200 wrap fn sig binders in fn ptr commit dd48b5e393814e1dbde3e8eb21bc111d301da6f6 Author: Ralf Jung Date: Fri Sep 15 15:59:47 2023 +0200 adjust constValue::Slice to work for arbitrary slice types commit c599761140ed1e3824a10d556395f178617e076a Author: Eduardo Sánchez Muñoz Date: Sun Sep 17 20:13:05 2023 +0200 rustc_hir_analysis: add a helper to check function the signature mismatches This function is now used to check `#[panic_handler]`, `start` lang item, `main`, `#[start]` and intrinsic functions. The diagnosis produced are now closer to the ones produced by trait/impl method signature mismatch. commit 59105177cc974182c61485e6695498f9c712c5d7 Merge: 81cd774bd02 3ca6c4916e4 Author: bors Date: Tue Sep 19 15:46:28 2023 +0000 Auto merge of #3054 - Vanille-N:spurious-fail, r=RalfJung Issue discovered in TB: spurious reads are not (yet) possible in a concurrent setting We discovered a week ago that in general, the current model of TB does not allow spurious reads because although reads provably never invalidate other reads, they migh invalidate writes. Consider the code ```rs fn f1(x: &u8) {} fn f2(y: &mut u8) -> &mut u8 { &mut *y } let mut data = 0; let _ = thread::spawn(|| { f1(&mut data) }; let _ = thread::spawn(|| { let y = f2(&mut data); *y = 42; }); ``` of which one possible interleaving is ```rs 1: retag x (&, protect) // x: [P]Frozen 2: retag y (&mut, protect) // y: [P]Reserved, x: [P]Frozen 1: return f1 // x: [P]Frozen -> Frozen, y: [P]Reserved 2: return f2 // x: Frozen, y: [P]Reserved -> Reserved 2: write y // x: Disabled, y: Active ``` that does not have UB. Assume enough barriers to force this specific interleaving, and consider that the compiler could choose to insert a spurious read throug `x` during the call to `f1` which would produce ```rs 1: retag x (&, protect) // x: [P]Frozen 2: retag y (&mut, protect) // y: [P]Reserved, x: [P]Frozen 1: spurious read x // x: [P]Frozen, y: [P]Reserved -> [P]Frozen 1: return f1 // x: [P]Frozen -> Frozen, y: [P]Frozen 2: return f2 // x: Frozen, y: [P]Frozen -> Frozen 2: write y // UB ``` Thus the target of the optimization (with a spurious read) has UB when the source did not. This is bad. SB is not affected because the code would be UB as early as `retag y`, this happens because we're trying to be a bit more subtle than that, and because the effects of a foreign read on a protected `&mut` bleed outside of the boundaries of the protector. Fortunately we have a fix planned, but in the meantime here are some `#[should_panic]` exhaustive tests to illustrate the issue. The error message printed by the `#[should_panic]` tests flags the present issue in slightly more general terms: it says that the sequence `retag x (&, protect); retag y (&mut, protect);` produces the configuration `C_source := x: [P]Frozen, x: [P]Reserved`, and that inserting a spurious read through `x` turns it into `C_target := x: [P]Frozen, y: [P]Reserved`. It then says that `C_source` is distinguishable from `C_target`, which means that there exists a sequence of instructions applied to both that triggers UB in `C_target` but not in `C_source`. It happens that one such sequence is `1: return f1; 2: return f2; 2: write y;` as shown above, but it is not the only one, as for example the interleaving `1: return f1; 2: write y;` is also problematic. commit 3ca6c4916e44377647fa2191d8763990d5523d1c Author: Neven Villani Date: Thu Aug 31 20:14:33 2023 +0200 Issue of the current model: spurious reads are not possible This occurs because in some interleavings, inserting a spurious read turns a Reserved into Frozen. We show here an exhaustive test (including arbitrary unknown code in two different threads) that makes this issue observable. commit 9b855a9f614be98c0e54da4d9ea0f10ffa288618 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 19 12:44:31 2023 +0000 Add missing with_no_trimmed_paths to CommentWriter::new() commit baee5ce1fcedc57063e10ead5b4fdb42c3f74c93 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 19 12:34:26 2023 +0000 Rustup to rustc 1.74.0-nightly (65ea825f4 2023-09-18) commit 5f3b867831724b84eb23085ff8faf0873ca03fd3 Merge: fbb276e933e 46b55ae1762 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue Sep 19 12:25:47 2023 +0000 Sync from rust 65ea825f4021eaf77f1b25139969712d65b435a4 commit cdf25c904e7dc6eee089e1ccebc5fbd05351dfb9 Author: Kriskras99 Date: Tue Sep 19 12:46:53 2023 +0200 Replace 'mutex' with 'lock' in RwLock documentation When copying the documentation for `clear_poison` from Mutex, not every occurence of 'mutex' was replaced with 'lock'. commit b30cefc775e92892f8d49a649bb09510bbbb79af Author: Ralf Jung Date: Sat Sep 16 09:36:22 2023 +0200 move ConstValue into mir this way we have mir::ConstValue and ty::ValTree as reasonably parallel commit 247d38d174c08421fc6558e0e466e9499d533658 Author: Ralf Jung Date: Sat Sep 16 09:36:22 2023 +0200 move ConstValue into mir this way we have mir::ConstValue and ty::ValTree as reasonably parallel commit 81cd774bd02ee352104df4ae7bcf21890b6c674f Merge: 25e7808021f 1e2813fa0f4 Author: bors Date: Tue Sep 19 05:51:07 2023 +0000 Auto merge of #3064 - rust-lang:rustup-2023-09-19, r=RalfJung Automatic sync from rustc commit 1e2813fa0f4a93552f33826957ea397d2365c23c Merge: aa6d6ba6c59 fd36553aa7b Author: The Miri Conjob Bot Date: Tue Sep 19 05:32:09 2023 +0000 Merge from rustc commit aa6d6ba6c59de1ee3e3dd7200a22345d6b84e70c Author: The Miri Conjob Bot Date: Tue Sep 19 05:25:27 2023 +0000 Preparing for merge from rustc commit 889e1b99bda1a845942c4c8b107d8a8c933a6dcb Merge: 5cba09c5767 b06b915dc04 Author: bors Date: Mon Sep 18 22:19:59 2023 +0000 Auto merge of #11530 - Alexendoo:zero-ptr-file-location, r=blyxyas Move zero_ptr to the casts module Also a bit of a touch up to the code while I was there changelog: none commit 5cba09c5767e22b637aaeb966ae7b58ba5a85338 Merge: 4022591cfd7 d9d25e98fca Author: bors Date: Mon Sep 18 21:31:48 2023 +0000 Auto merge of #11526 - Dev380:redundant-as-str, r=Manishearth Add redundant_as_str lint This lint checks for `as_str` on a `String` immediately followed by `as_bytes` or `is_empty` as those methods are available on `String` too. This could possibly also be extended to `&[u8]` in the future. changelog: New lint [`redundant_as_str`] #11526 commit d9d25e98fca4085cfe062700f6ca465abc20a52d Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:46:00 2023 -0400 Fix redundant_as_str .fixed file not being consistent commit 17d174d113fda8a21680a103d062d6fd589b4dc7 Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:39:09 2023 -0400 Reformat redundant_as_str ui test commit 522485343466bf81b9dedcb340d24f5287669c28 Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:37:27 2023 -0400 Remove periods from end of sentences in redundant_as_str comments commit 367ba9cd003e271dc4d7e354b1212fe3c60d3329 Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:36:10 2023 -0400 Add not redundant examples for redundant_as_str commit 00ca47b97d59ab3384c9786e5b38f0262f413384 Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:32:22 2023 -0400 Add more examples and comments to redundant_as_str test commit f2ab16eac139522ac5a9c6606c81e5967aec6d79 Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Mon Sep 18 16:08:02 2023 -0400 Add not triggering examples to redundant_as_str test commit 46b55ae1762de67bc69d3236830642842241999b Merge: f9f8bffaec5 b7cc765b602 Author: bors Date: Mon Sep 18 19:41:21 2023 +0000 Auto merge of #115748 - RalfJung:post-mono, r=oli-obk move required_consts check to general post-mono-check function This factors some code that is common between the interpreter and the codegen backends into shared helper functions. Also as a side-effect the interpreter now uses the same `eval` functions as everyone else to get the evaluated MIR constants. Also this is in preparation for another post-mono check that will be needed for (the current hackfix for) https://github.com/rust-lang/rust/issues/115709: ensuring that all locals are dynamically sized. I didn't expect this to change diagnostics, but it's just cycle errors that change. r? `@oli-obk` commit e9dc753b7ba7ebe2d384d53a9b4a5baacc68c1cf Merge: 66aa7f7cac0 3226e4b0108 Author: bors Date: Mon Sep 18 19:41:21 2023 +0000 Auto merge of #115748 - RalfJung:post-mono, r=oli-obk move required_consts check to general post-mono-check function This factors some code that is common between the interpreter and the codegen backends into shared helper functions. Also as a side-effect the interpreter now uses the same `eval` functions as everyone else to get the evaluated MIR constants. Also this is in preparation for another post-mono check that will be needed for (the current hackfix for) https://github.com/rust-lang/rust/issues/115709: ensuring that all locals are dynamically sized. I didn't expect this to change diagnostics, but it's just cycle errors that change. r? `@oli-obk` commit 9102816bc4deca950b66cce402ea45573acc8fa0 Author: Eduardo Sánchez Muñoz Date: Mon Sep 18 20:11:01 2023 +0200 Prevent using `#[target_feature]` on lang item functions commit 6192690b92d32d0d8511e1dd33b7cd35a52d6209 Author: Urgau Date: Tue Sep 5 15:14:53 2023 +0200 Add clippy like expr_or_init fn to rustc LateContext commit 6fd5dc8860dc0060b54a43dea07298142e6944f7 Author: Oli Scherer Date: Mon Sep 18 14:37:19 2023 +0000 Prototype using const generic for simd_shuffle IDX array commit 1a01e57d277e3b2668c9c18fd44ae48399a4cf48 Author: Oli Scherer Date: Mon Sep 18 14:37:19 2023 +0000 Prototype using const generic for simd_shuffle IDX array commit e8b8ddd17e93875b6536224c598790117d4c929e Author: lcnr Date: Thu Sep 14 16:21:54 2023 +0200 remove provisional cache commit 4022591cfd7890e3db8e477986d47a336cd230a7 Merge: ea16f812beb 3665a4102bc Author: bors Date: Mon Sep 18 14:21:48 2023 +0000 Auto merge of #11517 - mojave2:issue-11426, r=Alexendoo fix ICE by `u64::try_from()` changelog: Fix the ICE in [`cast_possible_truncation`], when the `Shr` bits is larger than `u64::MAX` fix #11426 commit b8b420cc79dc18423a9bf59ee3397a398e9aac2a Author: Guillaume Gomez Date: Mon Sep 18 15:47:24 2023 +0200 Improve code readability by moving the retrieval of closures inside async functions right besides other closures handling. Add doc comment explaining what `MutablyUsedVariablesCtxt::prev_move_to_closure` is about. commit ea16f812beb8e1c709d450fcc0d2c4bb8e6f50dc Merge: c92de586928 32519528dfe Author: bors Date: Mon Sep 18 13:12:18 2023 +0000 Auto merge of #11531 - Alexendoo:remark-deps, r=flip1995 Update remark CI deps [Remark v15](https://github.com/remarkjs/remark/releases/tag/15.0.0) was just released that needs a newer node version, this updates us to 18 (the current LTS) Also updates mdbook while we're at it changelog: none commit 32519528dfe8743d006e337c8105868761922d03 Author: Alex Macleod Date: Mon Sep 18 12:42:37 2023 +0000 Update remark CI deps commit b06b915dc04a577cfe599d7e44137124ba12c877 Author: Alex Macleod Date: Mon Sep 18 12:10:35 2023 +0000 Move zero_ptr to the casts module commit c92de5869282c189865f7ebfc039752d447c6d2c Merge: 251a475b724 32d3387c80b Author: bors Date: Mon Sep 18 09:04:44 2023 +0000 Auto merge of #11523 - Alexendoo:used-underscore-bindings-lint-levels, r=xFrednet used_underscore_bindings: respect lint levels on the binding definition Fixes #11520 Fixes #947 Also ignores usages of `PhantomData` changelog: none commit 12a1b55afdf617956d72e52640dc293b80895fdd Author: Ralf Jung Date: Sat Sep 16 13:56:16 2023 +0200 better ICE than sorry commit 01056c5aae63c546c3d988a0b46e502a3a2a7baf Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Sun Sep 17 18:10:21 2023 -0400 Fix missing semicolon in redundant_as_str docstring example commit 1c9f3bef8bb80dc8706e4595a262fe8825ccf74a Author: Dev381 <49997896+Dev380@users.noreply.github.com> Date: Sun Sep 17 17:50:45 2023 -0400 Add redundant_as_str lint This lint checks for `as_str` on a `String` immediately followed by `as_bytes` or `is_empty` as those methods are available on `String` too. This could possibly also be extended to `&[u8]` in the future. commit 32d3387c80b59ad85756aa66237aa6d2a0eca884 Author: Alex Macleod Date: Sun Sep 17 14:33:06 2023 +0000 used_underscore_bindings: respect lint levels on the binding definition commit 251a475b724a81ffcfd0113820492a329feeef5c Merge: 7b5e0199dab 79247d95f7e Author: bors Date: Sun Sep 17 13:48:40 2023 +0000 Auto merge of #11511 - Jarcho:split_borrow, r=llogiq Split `needless_borrow` into two lints Splits off the case where the borrow is used as a generic argument to a function. I think the two cases are different enough to warrant a separate lint. The tests for the new lint have been reordered to group related parts together. Two warning have been dropped, one looked like it was testing the generic argument form, but it ends up triggering the auto-deref variant. The second was just a redundant test that didn't do anything interesting. An issue with cycle detection is also included. The old version was checking if a cycle was reachable from a block when it should have been checking if the block is part or a cycle. As a side note, I'm liking the style of just jamming all the tests into separate scopes in main. changelog: Split off `needless_borrows_for_generic_args` from `needless_borrow` commit 79247d95f7ec00019cc26db20a07d4f1c1f335aa Author: Jason Newcomb Date: Fri Sep 15 07:07:34 2023 -0400 Split part of `needless_borrow` into `needless_borrows_for_generic_args` commit 558ae4c6a8a5a81c5b0cb3c7828e622201ba33ee Author: y21 <30553356+y21@users.noreply.github.com> Date: Sun Sep 17 15:34:32 2023 +0200 [`redundant_guards`]: lint if the pattern is on the LHS commit 3665a4102bce2cd6b09a7aea1b405cc640e076d8 Author: mojave2 Date: Sun Sep 17 19:44:25 2023 +0800 fix ICE by `u64::try_from()` commit 66aa7f7cac015730fa96ebb9b63e5554f97f7d1d Merge: 21216297e97 1c27ba931b5 Author: Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> Date: Sun Sep 17 11:23:24 2023 +0000 Rollup merge of #115477 - kellerkindt:stabilized_int_impl, r=dtolnay Stabilize the `Saturating` type Closes #87920 Closes #92354 Stabilization report https://github.com/rust-lang/rust/issues/87920#issuecomment-1652346124 FCP https://github.com/rust-lang/rust/issues/87920#issuecomment-1676438885 commit 7b5e0199dab373b1a379e4ea7161d1440509f3c7 Merge: ef736489e78 2ec6f3b1ed2 Author: bors Date: Sun Sep 17 06:37:45 2023 +0000 Auto merge of #11515 - y21:filter_map_bool_then_peel_refs, r=Jarcho [`filter_map_bool_then`]: include multiple derefs from adjustments In #11506 this lint was improved to suggest one deref if the bool is behind references (fixed the FP #11503), however it might need multiple dereferences if the bool is behind multiple layers of references or custom derefs. E.g. `&&&bool` needs `***b`. changelog: [`filter_map_bool_then`]: suggest as many dereferences as there are needed to get to the bool commit 5b790ff9e0effa9f742ce8a7b896a35c767fb131 Author: mojave2 Date: Sun Sep 17 12:54:00 2023 +0800 fix FP with needless_raw_string_hashes commit ef736489e7842c0293ad289e15b18f5d0f3661b4 Merge: f54275f20fb 67f0ba4af8b Author: bors Date: Sat Sep 16 22:02:10 2023 +0000 Auto merge of #11468 - mojave2:issue-11465, r=blyxyas add extra `byref` checking for the guard's local changelog: [`redundant_guards`]: Now checks if the variable is bound using `ref` before linting. The lint should not be emitted, when the local variable is bind by-ref in the pattern. fixes #11465 commit 3cad6237166dc71e2b75a9e60d5058f2876e1959 Author: Chen Chen <0109chenchen@gmail.com> Date: Sun Sep 17 02:42:12 2023 +0800 更新 cast_lossless.rs Co-authored-by: Timo <30553356+y21@users.noreply.github.com> commit 25e7808021ff1554f91541eaad7dd5d170a86f91 Merge: 039875986ca 09fd7a8722f Author: bors Date: Sat Sep 16 16:58:16 2023 +0000 Auto merge of #3062 - pitaj:subtree-update, r=RalfJung triagebot exclude_labels -> exclude_titles https://github.com/rust-lang/triagebot/pull/1720 commit 09fd7a8722fb9634706dcd6ddb88473f4cc6bdf3 Author: Peter Jaszkowiak Date: Fri Sep 15 21:43:14 2023 -0600 triagebot exclude_labels -> exclude_titles commit af2a8478ba3228ede92ff799b17ac2408fc6347f Author: mojave2 Date: Sat Sep 16 23:17:47 2023 +0800 fix cast_lossless with macro call commit 67f0ba4af8be42d361adc8d047121fe6c820c0d4 Author: Chen Chen <0109chenchen@gmail.com> Date: Sat Sep 16 22:12:40 2023 +0800 Update clippy_lints/src/matches/redundant_guards.rs fix typo Co-authored-by: Alejandra González commit 2ec6f3b1ed22c3fa0b20eda5cf335c54f81b4462 Author: y21 <30553356+y21@users.noreply.github.com> Date: Sat Sep 16 15:13:44 2023 +0200 also count derefs through custom `Deref` impls commit 860e800fa08734ff9d15a67115f8220e5fa2202e Author: y21 <30553356+y21@users.noreply.github.com> Date: Sat Sep 16 14:14:51 2023 +0200 [`filter_map_bool_then`]: peel as many refs as needed commit d34e15e740633e5329672ccea90e19e09e53c7f4 Author: Ralf Jung Date: Sat Sep 16 09:09:25 2023 +0200 thir::pattern: update some comments and error type names commit f54275f20fb4aa20e28e6f082fac8cfc044965a4 Merge: 3f9db9025d9 7426c83d8f5 Author: bors Date: Sat Sep 16 10:22:33 2023 +0000 Auto merge of #11509 - mojave2:issue-11502, r=llogiq fix FP of let_unit_value on async fn args changelog: [`let_unit_value`]: fix the FalsePostive on async fn arguments fix #11502 commit fbb276e933eadcd95aacd23c969de2e619d7004e Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat Sep 16 10:12:33 2023 +0000 Update some dependencies commit d49123ddc9ccd18282527d90abb17b73f6b41d13 Author: Ralf Jung Date: Sat Sep 16 11:43:34 2023 +0200 fix a comment about assert_receiver_is_total_eq commit 3f9db9025d9a210e1e3c0dbac54f52cb25fd6784 Merge: 59636a2aa3f 1d76eede991 Author: bors Date: Sat Sep 16 06:19:09 2023 +0000 Auto merge of #11507 - J-ZhengLi:issue11485, r=dswij trigger [`transmute_null_to_fn`] on chain of casts fixes: #11485 changelog: trigger [`transmute_null_to_fn`] on chain of casts commit 59636a2aa3f0189b75936170e24f6f83ff993ccc Merge: daadab515a5 18f36897ef0 Author: bors Date: Sat Sep 16 06:04:59 2023 +0000 Auto merge of #11301 - y21:issue11300, r=dswij [`useless_conversion`]: don't lint if type parameter has unsatisfiable bounds for `.into_iter()` receiver Fixes #11300. Before this PR, clippy assumed that if it sees a `f(x.into_iter())` call and the type at that argument position is generic over any `IntoIterator`, then the `.into_iter()` call must be useless because `x` already implements `IntoIterator`, *however* this assumption is not right if the generic parameter has more than just the `IntoIterator` bound (because other traits can be implemented for the IntoIterator target type but not the IntoIterator implementor, as can be seen in the linked issue: `<[i32; 3] as IntoIterator>::IntoIter` satisfies `ExactSizeIterator`, but `[i32; 3]` does not). So, this PR makes it check that the type parameter only has a single `IntoIterator` bound. It *might* be possible to check if the type of `x` in `f(x.into_iter())` satisfies all the bounds on the generic type parameter as defined on the function (which would allow removing the `.into_iter()` call even with multiple bounds), however I'm not sure how to do that, and the current fix should always work. **Edit:** This PR has been changed to check if any of the bounds don't hold for the type of the `.into_iter()` receiver, so we can still lint in some cases. changelog: [`useless_conversion`]: don't lint `.into_iter()` if type parameter has multiple bounds commit fed036a57c96d91ac632f0bd40a27ef78b5b96c6 Author: Jason Newcomb Date: Fri Sep 15 07:06:50 2023 -0400 Fix cycle detection in `needless_borrow` commit 7426c83d8f5d1688763642503b59d0f0f653a3f5 Author: mojave2 Date: Sat Sep 16 00:05:57 2023 +0800 add a test case commit daadab515a5df78c1745d306c59095abad4fcc56 Merge: eaf640dcf0f 981e96008b5 Author: bors Date: Fri Sep 15 15:38:55 2023 +0000 Auto merge of #11483 - y21:path_ends_with, r=Alexendoo new lint: `path_ends_with_ext` Closes #11479 Not sure if it needs more test cases. I couldn't come up with any other ones, but it is a pretty simple lint logic wise with not too many checks changelog: new lint: [`path_ends_with_ext`] commit 981e96008b58d34e9c52b0aa3b318974c75b9d1d Author: y21 <30553356+y21@users.noreply.github.com> Date: Mon Sep 11 22:46:15 2023 +0200 new lint: `path_ends_with_ext` commit eaf640dcf0fa3c3ec6a5210f9c26edcea045e6b9 Merge: e609279b2c0 c9b212d5ffa Author: bors Date: Fri Sep 15 13:13:16 2023 +0000 Auto merge of #11506 - mojave2:issue-11503, r=giraffate fix filter_map_bool_then with a bool reference changelog: [`filter_map_bool_then`]: Fix the incorrect autofix when the `bool` in question is a reference. fix #11503 commit e609279b2c0fd0626e42700b11601a071599f1a7 Merge: 2c629cc137d f598bb75d47 Author: bors Date: Fri Sep 15 12:59:15 2023 +0000 Auto merge of #11484 - mkrasnitski:fix-11302, r=Jarcho [`extra_unused_type_parameters`]: Fix edge case FP for parameters in where bounds Generic parameters can end up being used on the left side of where-bounds if they are not directly bound but instead appear nested in some concrete generic type. Therefore, we should walk the left side of where bounds, but only if the bounded type is *not* a generic param, in which case we still need to ignore the bound. Fixes #11302 changelog: [`extra_unused_type_parameters`]: Fix edge case false positive for parameters in where bounds commit 21216297e97569459ad186b6aeba2bebce353f2f Merge: 9756a135807 da4244e79c4 Author: bors Date: Fri Sep 15 09:55:31 2023 +0000 Auto merge of #115851 - Alexendoo:clippy-doc-hidden-headers, r=flip1995 Ignore `#[doc(hidden)]` functions in clippy doc lints Fixes https://github.com/rust-lang/rust-clippy/issues/11501 The implementation before #115689 had a check for unsugared doc comments that also happened to catch `#[doc(hidden)]`, this adds the check back in more explicitly https://github.com/rust-lang/rust/blob/852bf4e51bf260550cd1a280d2146f1c0641b1e8/src/tools/clippy/clippy_lints/src/doc.rs#L526-L529 r? `@flip1995` commit 2c629cc137de1196a0a144e4f2cb778b1f64538b Merge: 6734e96ba4f a2a31a0a2fd Author: bors Date: Fri Sep 15 09:34:13 2023 +0000 Auto merge of #11504 - Alexendoo:type-lints-closures, r=xFrednet Ignore closures for some type lints Fixes #11417 `hir_ty_to_ty` is used in a couple of the `!is_local` lints, which doesn't play nicely inside bodies changelog: none commit f9f8bffaec5264366d9c2bc74f865a473f2a2369 Author: Ralf Jung Date: Sat Sep 9 09:23:56 2023 +0200 fix gcc, cranelift build commit 89f0d18bc8cb466a434a2757f43d64f1f101df61 Author: Ralf Jung Date: Fri Sep 8 08:48:41 2023 +0200 clarify PassMode::Indirect as well commit c81888eab32e09318a9b95fdad22aea27f6933ea Author: mojave2 Date: Fri Sep 15 15:05:43 2023 +0800 fix FP of let_unit_value on async fn args commit c9b212d5ffa5dcfe36ed41658c71dcbcbf949dd8 Author: mojave2 Date: Fri Sep 15 14:23:58 2023 +0800 fix filter_map_bool_then with a bool reference commit 039875986ca5cb155c452e1d2e14e3afcf71aa8e Merge: 8cd31eadba1 faa57a71fa8 Author: bors Date: Fri Sep 15 05:47:33 2023 +0000 Auto merge of #3061 - rust-lang:rustup-2023-09-15, r=saethlin Automatic sync from rustc commit faa57a71fa8e7deb1a17e056c74ab188f90dfe4a Merge: 3915c4d1143 c230637b92a Author: The Miri Conjob Bot Date: Fri Sep 15 05:30:42 2023 +0000 Merge from rustc commit 3915c4d1143f2ca5977df0a4804734a066b38459 Author: The Miri Conjob Bot Date: Fri Sep 15 05:24:07 2023 +0000 Preparing for merge from rustc commit 1d76eede99126dc6534a0d89dbf04121cd990042 Author: J-ZhengLi Date: Fri Sep 15 12:24:45 2023 +0800 trigger [`transmute_null_to_fn`] on chain of casts commit 6734e96ba4f0872e1245665d8c7c85e56c61fd1f Merge: b27fc10aa89 3c0fc158483 Author: bors Date: Thu Sep 14 23:05:24 2023 +0000 Auto merge of #11505 - Alexendoo:metadata-collector-truncate, r=Manishearth Truncate files when opening in metadata-collector Fixes the issue seen here https://github.com/rust-lang/rust-clippy/pull/11483#discussion_r1324687136 and in a couple other PRs The changelog file was opened without truncating it, so if the new version is shorter than the old one stray contents would remain at the end of the file The other two files first removed the file so didn't have this problem, but in all cases we now use `fs::write`/`File::create` which is write + create + truncate changelog: none commit 3c0fc15848395ed5ef714c8817df8bd4f1bc430f Author: Alex Macleod Date: Thu Sep 14 22:17:51 2023 +0000 Truncate files when opening in metadata-collector commit a2a31a0a2fd356f681c78498719dea8aa2523190 Author: Alex Macleod Date: Thu Sep 14 21:20:50 2023 +0000 Ignore closures for some type lints commit b7cc765b602bcb1e0a0a8883b6d982c47b3236c1 Author: Ralf Jung Date: Mon Sep 11 23:09:11 2023 +0200 don't point at const usage site for resolution-time errors also share the code that emits the actual error commit 3226e4b01089b4e8e8d474a8d498bb0c68e76ed2 Author: Ralf Jung Date: Mon Sep 11 23:09:11 2023 +0200 don't point at const usage site for resolution-time errors also share the code that emits the actual error commit 3113fef3a357ab8b39672be85951763a26261fd4 Author: Ralf Jung Date: Mon Sep 11 09:52:45 2023 +0200 move required_consts check to general post-mono-check function commit 1d49cb6118c346871f85dc3a0e7bb3330b09687b Author: Ralf Jung Date: Mon Sep 11 09:52:45 2023 +0200 move required_consts check to general post-mono-check function commit 9756a135807b51f6be740aed0103a29721be123c Merge: eb545d75689 ab08a3d7b21 Author: bors Date: Thu Sep 14 19:56:55 2023 +0000 Auto merge of #115677 - matthewjasper:let-expr-recovery, r=b-naber Improve invalid let expression handling - Move all of the checks for valid let expression positions to parsing. - Add a field to ExprKind::Let in AST/HIR to mark whether it's in a valid location. - Suppress some later errors and MIR construction for invalid let expressions. - Fix a (drop) scope issue that was also responsible for #104172. Fixes #104172 Fixes #104868 commit 5c7a87c9bac1432cea697fa00a328816fd62b9a6 Merge: 02e5f387fad e048674ea53 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 14 21:05:03 2023 +0200 Merge pull request #1393 from onur-ozkan/rustfmt-group-imports organize import sections with rustfmt `group_imports` commit e048674ea53ee8b774c52ad17da9b570ee84ec1d Author: onur-ozkan Date: Thu Sep 14 16:46:25 2023 +0300 organize import sections with rustfmt `group_imports` Signed-off-by: onur-ozkan commit 02e5f387fad115d172ef09697faffd8a4b90b29f Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 7 13:36:03 2023 +0000 Add debug tracing for failed commands commit d8c1393557eb7f893184af54b21ce29ee3d08432 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 14 18:34:31 2023 +0000 Avoid mir_operand_get_const_val for simd_shuffle and cmpps and cmppd commit aab17ccd19194fe4c5313776d864e80e085168c3 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 14 17:58:00 2023 +0000 Fix rustc test suite commit da4244e79c49d4a938c02eebb955f9b217001213 Author: Alex Macleod Date: Thu Sep 14 17:47:36 2023 +0000 Ignore `#[doc(hidden)]` functions in clippy doc lints commit b27fc10aa890a8cbc00f7d361ffd58da40dcd6ea Merge: 0273ed3afd1 c29de92d85f Author: bors Date: Thu Sep 14 17:28:51 2023 +0000 Auto merge of #11444 - Alexendoo:find-format-args-lifetime-crimes, r=flip1995 Return a value from find_format_args instead of using a callback r? `@flip1995` changelog: none commit b67a1c4ea71ebe6c66ff37a5e783e3dbc5a3ebb6 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 14 16:51:24 2023 +0000 Rustup to rustc 1.74.0-nightly (8142a319e 2023-09-13) commit 214d474a854fc45e589d9bb37e77220c4a5356b1 Merge: d72f7109ede 1956fb84f3a Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 14 16:48:54 2023 +0000 Sync from rust 8142a319ed5c1d1f96e5a1881a6546e463b77c8f commit c29de92d85f22bdc8814e87e4d4ee9f46d3c679e Author: Alex Macleod Date: Fri Sep 1 17:05:30 2023 +0000 Return a value from find_format_args instead of using a callback commit eb545d75689cdebcfd2884292085f470a4702784 Merge: 477a9b88bf3 272df70b509 Author: bors Date: Thu Sep 14 13:42:30 2023 +0000 Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk treat host effect params as erased in codegen This fixes the changes brought to codegen tests when effect params are added to libcore, by not attempting to monomorphize functions that get the host param by being `const fn`. r? `@oli-obk` commit 477a9b88bf31168e747a463b4942a8d64ae5917d Author: Ralf Jung Date: Tue Sep 12 14:44:38 2023 +0200 fix clippy (and MIR printing) handling of ConstValue::Indirect slices commit 272df70b50992885dcc70b8c34471234985b3be2 Author: Deadbeef Date: Wed Sep 13 13:55:23 2023 +0000 treat host effect params as erased generics in codegen This fixes the changes brought to codegen tests when effect params are added to libcore, by not attempting to monomorphize functions that get the host param by being `const fn`. commit 8d3bbb09640479b43b48a3c3a81580a1d3fbbc04 Author: mojave2 Date: Thu Sep 14 14:57:05 2023 +0800 handle the byref binding in the struct pattern commit 90d894e122d2223126ffcce79910659c2a211ea7 Author: Ralf Jung Date: Tue Sep 12 08:42:36 2023 +0200 make it more clear which functions create fresh AllocId commit b2d5d68c58a745c80bc0187dba8c85e1519faabc Author: Ralf Jung Date: Tue Sep 12 07:49:25 2023 +0200 cleanup op_to_const a bit; rename ConstValue::ByRef → Indirect commit a5b81faef0c0c70a7a254c5146e70629a2d5c923 Author: Ralf Jung Date: Tue Sep 12 07:49:25 2023 +0200 cleanup op_to_const a bit; rename ConstValue::ByRef → Indirect commit 2aaaeb4e8166cf7ba52cf606eec2219730a06395 Author: Ralf Jung Date: Mon Sep 11 20:01:48 2023 +0200 use AllocId instead of Allocation in ConstValue::ByRef commit d1ea6997e8aa05dc145c33ba5e38a37901950404 Author: Ralf Jung Date: Mon Sep 11 20:01:48 2023 +0200 use AllocId instead of Allocation in ConstValue::ByRef commit 0273ed3afd1cb032655aef0019c448b9a6950731 Merge: 2009b58df27 0c7dcba28a5 Author: bors Date: Thu Sep 14 04:55:09 2023 +0000 Auto merge of #11497 - Alexendoo:remove-derive-new, r=dswij Remove `derive_new` test dependency It is the last thing depending on syn 1.0 in clippy changelog: none commit 2009b58df27aab2463eaaba8b870aee09caabf1e Merge: b788addfcc9 26c0f975797 Author: bors Date: Wed Sep 13 23:46:27 2023 +0000 Auto merge of #11452 - y21:issue11165, r=Centri3 [`len_without_is_empty`]: follow type alias to find inherent `is_empty` method Fixes #11165 When we see an `impl B` and `B` is a type alias to some type `A`, then we need to follow the type alias to look for an `is_empty` method on the aliased type `A`. Before this PR, it'd get the inherent impls of `B`, which there aren't any and so it would warn that there isn't an `is_empty` method even if there was one. Passing the type alias `DefId` to `TyCtxt::type_of` gives us the aliased `DefId` (or simply return the type itself if it wasn't a type alias) so we can just use that changelog: [`len_without_is_empty`]: follow type alias to find inherent `is_empty` method commit 06985915273091b50aa7cd72d20ec0cf50970407 Merge: 5cd391c4adf 471469d30fa Author: bors Date: Wed Sep 13 20:28:02 2023 +0000 Auto merge of #115790 - flip1995:clippyup, r=Manishearth Update Clippy r? `@Manishearth` commit 0c7dcba28a502f8a6e9a5da533cb74feda0adb4c Author: Alex Macleod Date: Wed Sep 13 18:58:47 2023 +0000 Remove `derive_new` test dependency It is the last thing depending on syn 1.0 in clippy commit 1956fb84f3a5d128cd18ba413a8042d6ee0a4e66 Merge: 9475cdb02dc 72fb4b8f316 Author: Matthias Krüger Date: Wed Sep 13 18:37:42 2023 +0200 Rollup merge of #115798 - RalfJung:non_1zst_field, r=wesleywiser add helper method for finding the one non-1-ZST field commit 9475cdb02dcd55289f582dec96a797db04b693d1 Merge: 8e6f68be390 4f6e9fd8d3b Author: Matthias Krüger Date: Wed Sep 13 18:37:41 2023 +0200 Rollup merge of #115736 - Zoxc:time-cleanup, r=wesleywiser Remove `verbose_generic_activity_with_arg` This removes `verbose_generic_activity_with_arg` and changes users to `generic_activity_with_arg`. This keeps the output of `-Z time` readable while these repeated events are still available with the self profiling mechanism. commit e3267b1fe7bf90348f76b42fba6ebd09ef8ef714 Author: Guillaume Gomez Date: Wed Sep 13 14:39:41 2023 +0200 Fix mutaby used async function argument in closure for `needless_pass_by_ref_mut` commit 5cd391c4adf0a50d07fe403ce7ddcbeb9922c8b9 Author: Ralf Jung Date: Tue Sep 12 23:47:47 2023 +0200 make the set of methods between our two Const types more consistent commit 8e6f68be390a1daa8e4d203dde630f26274ca84b Author: Ralf Jung Date: Tue Sep 12 23:28:25 2023 +0200 make the eval() functions on our const types return the resulting value commit 7f870201d3c46f40e6be34424ded337fe702fecb Author: mojave2 Date: Wed Sep 13 11:13:51 2023 +0800 add `byref` checking for the guard's local commit 72fb4b8f3160751af92185d4a454a09884a90b81 Author: Ralf Jung Date: Tue Sep 12 20:51:00 2023 +0200 add helper method for finding the one non-1-ZST field commit 0cb22a66eb577254b8a507ef75b7f10728b396ca Author: ouz-a Date: Tue Sep 12 21:09:29 2023 +0300 very verbose error handling commit 471469d30facd25ed3072524694e369aeb72082c Author: Philipp Krones Date: Tue Sep 12 18:13:53 2023 +0200 Merge commit '98363cbf6a7c3f8b571a7d92a3c645bb4376e4a6' into clippyup commit b788addfcc955368b9771b77d312c248fab60253 Merge: cb057019d46 cc8c0e00991 Author: bors Date: Tue Sep 12 16:43:14 2023 +0000 Auto merge of #11473 - Alexendoo:format-args-span-parents, r=dswij Ignore span's parents in `collect_ast_format_args`/`find_format_args` Fixes #11470, covers some cases missed by #10980 Can't have a test yet because of #11126 but it works locally changelog: none r? `@dswij` commit cb057019d46b823f142b6cc201319586e61471a8 Merge: 98363cbf6a7 f136e1634a8 Author: bors Date: Tue Sep 12 16:09:06 2023 +0000 Auto merge of #11413 - jonboh:master, r=Alexendoo new unnecessary_map_on_constructor lint changelog: [`unnecessary_map_on_constructor`]: adds lint for cases in which map is not necessary. `Some(4).map(myfunction)` => `Some(myfunction(4))` Closes https://github.com/rust-lang/rust-clippy/issues/6472 Note that the case mentioned in the issue `Some(..).and_then(|..| Some(..))` is fixed by a chain of lint changes. This PR completes the last part of that chain. By `bind_instead_of_map`[lint](https://rust-lang.github.io/rust-clippy/master/index.html#/bind_instead_of_map): `Some(4).and_then(|x| Some(foo(4)))` => `Some(4).map(|x| foo)` By `redundant_closure` [lint](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure): `Some(4).map(|x| foo)` => `Some(4).map(fun)` Finally by this PR `unnecessary_map_on_constructor`: `Some(4).map(fun)` => `Some(fun(4))` I'm not sure this is the desired behavior for clippy and if it should be addressed in another issue/PR. I'd be up to give it a try if that's the case. commit f136e1634a8d834d32deb89273717227eedaf153 Author: jonboh Date: Sat Aug 26 16:26:09 2023 +0200 new unnecessary_map_on_constructor lint commit feb80025023a7cade71003309ae0806bda82f251 Author: Chinedu Francis Nwafili Date: Tue Sep 12 03:25:41 2023 -0400 Fix formatting commit 22b1acb45500f34bb100f7da4d5e90fcc37bca92 Author: ouz-a Date: Tue Sep 12 10:28:37 2023 +0300 match on elem first commit 7db9c3c1a6ef12e3402c1cf439a203faeab1ca2c Author: Chinedu Francis Nwafili Date: Tue Sep 12 03:11:11 2023 -0400 Tests passing commit b643f20f464c93894c9347c8bc34a46caf8355f0 Merge: 54f3ddb84a2 e88a5561241 Author: bors Date: Tue Sep 12 01:45:24 2023 +0000 Auto merge of #115689 - Alexendoo:clippy-doc-comments, r=notriddle,Manishearth,flip1995 Reuse rustdoc's doc comment handling in Clippy Moves `source_span_for_markdown_range` and `span_of_attrs` (renamed to `span_of_fragments`) to `rustc_resolve::rustdoc` so it can be used in Clippy Fixes https://github.com/rust-lang/rust-clippy/issues/10277 Fixes https://github.com/rust-lang/rust-clippy/issues/5593 Fixes https://github.com/rust-lang/rust-clippy/issues/10263 Fixes https://github.com/rust-lang/rust-clippy/issues/2581 commit f598bb75d47c45b69b3fe2952d53fcccf870e8b3 Author: Michael Krasnitski Date: Mon Sep 11 21:43:27 2023 -0400 Walk the left side of where bounds if the bounded type is not a generic parameter commit ab08a3d7b2143154f16b82c388bb355aff6c4b4b Author: Matthew Jasper Date: Fri Sep 8 16:14:47 2023 +0000 Update tools and fulldeps tests commit 54f3ddb84a2bbdbb0b60f1d38ea3deae03286b30 Author: Alex Macleod Date: Sun Sep 10 18:17:47 2023 +0000 Call `LateLintPass::check_attribute` from `with_lint_attrs` commit 4f6e9fd8d3b32cac422524da5ee95a296a482794 Author: John Kåre Alsaker Date: Sun Sep 10 13:15:46 2023 +0200 Remove `verbose_generic_activity_with_arg` commit e88a556124189e3ee23841238252b3831b3af966 Author: Alex Macleod Date: Fri Sep 8 22:39:20 2023 +0000 Reuse rustdoc's doc comment handling in Clippy commit c41e7794cd4acf979204d7f68aca74b828a389b2 Merge: 6285086ead0 4ecfd30a867 Author: bors Date: Fri Sep 8 17:20:23 2023 +0000 Auto merge of #115418 - Zoxc:freeze-source, r=oli-obk Use `Freeze` for `SourceFile` This uses the `Freeze` type in `SourceFile` to let accessing `external_src` and `lines` be lock-free. Behavior of `add_external_src` is changed to set `ExternalSourceKind::AbsentErr` on a hash mismatch which matches the documentation. `ExternalSourceKind::Unneeded` was removed as it's unused. Based on https://github.com/rust-lang/rust/pull/115401. commit cc8c0e00991ccf692b9b12bf887cefac99fffa04 Author: Alex Macleod Date: Fri Sep 8 12:40:21 2023 +0000 Ignore span's parents in `collect_ast_format_args`/`find_format_args` commit b5941a2fd5f01de1888c2e781883b6c3cbdaeef5 Author: John Kåre Alsaker Date: Sun Sep 3 06:31:56 2023 +0200 Partially outline code inside the panic! macro commit 6a02baaa3d9c471577037a053ee8ed50a9327f7d Author: John Kåre Alsaker Date: Sun Sep 3 06:31:56 2023 +0200 Partially outline code inside the panic! macro commit e4af4e50831a23485e3e05646097bea26ff97a79 Author: Michael Goulet Date: Fri Sep 8 03:00:59 2023 +0000 Stabilize impl_trait_projections commit d72f7109ede688200c4ffdc0453457a66552f47b Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 7 12:03:27 2023 +0000 Update steps to testing rustc changes for upstream changes commit 5ae94e91f02a5e26162db20e2b306aeebd79a2d7 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 7 11:54:01 2023 +0000 Rustup to rustc 1.74.0-nightly (e3abbd499 2023-09-06) commit 28f12f057d04057d2f8ce782fb5c18e2f60db73f Merge: dda103b1e33 6285086ead0 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu Sep 7 11:45:29 2023 +0000 Merge branch 'sync_from_rust' commit 0f74faf1584b5639a214ef794026bef2d842bfa3 Author: John Kåre Alsaker Date: Thu Aug 31 22:12:47 2023 +0200 Use `Freeze` for `SourceFile.lines` commit 4ecfd30a8671baeb36b12c4827255ce89a740fd3 Author: John Kåre Alsaker Date: Thu Aug 31 22:12:47 2023 +0200 Use `Freeze` for `SourceFile.lines` commit 6285086ead0a603da516d2d051a07a9d87097883 Merge: d4f12a5ed3e f2211c52425 Author: bors Date: Thu Sep 7 03:56:43 2023 +0000 Auto merge of #115616 - bjorn3:sync_cg_clif-2023-09-06, r=bjorn3 Sync rustc_codegen_cranelift Not much changed this time. Mostly doing this sync to make it easier to run the entire test suite on the in-tree version. r? `@ghost` `@rustbot` label +A-codegen +A-cranelift +T-compiler commit d4f12a5ed3e574b911965f0c2323e1008ee87afd Merge: 61a0b77e175 4cd51770154 Author: bors Date: Wed Sep 6 22:26:37 2023 +0000 Auto merge of #115580 - eduardosm:stdarch-intrinsics, r=davidtwco,bjorn3 Update stdarch submodule and remove special handling in cranelift codegen for some AVX and SSE2 LLVM intrinsics https://github.com/rust-lang/stdarch/pull/1463 reimplemented some x86 intrinsics to avoid using some x86-specific LLVM intrinsics: * Store unaligned (`_mm*_storeu_*`) use `<*mut _>::write_unaligned` instead of `llvm.x86.*.storeu.*`. * Shift by immediate (`_mm*_s{ll,rl,ra}i_epi*`) use `if` (srl, sll) or `min` (sra) to simulate the behaviour when the RHS is out of range. RHS is constant, so the `if`/`min` will be optimized away. This PR updates the stdarch submodule to pull these changes and removes special handling for those LLVM intrinsics from cranelift codegen. I left gcc codegen untouched because there are some autogenerated lists. commit f2211c52425efb255ae22457ad6d07ec6e354c22 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed Sep 6 18:51:03 2023 +0000 Merge commit 'dda103b1e33c4902deca8bccf614991ada781fa6' into sync_cg_clif-2023-09-06 commit 98c94ec72f5c9319b9192d688c5abd851dcd2d15 Author: Ralf Jung Date: Wed Sep 6 17:58:21 2023 +0200 fix typo Co-authored-by: Marcin S. commit ad7045e160b77a6cedea61e85dfbfd3497da05fd Author: Ralf Jung Date: Tue Sep 5 23:06:35 2023 +0200 still accept references to u8 slices and str in packed fields commit 8b3435c10f458b840d9cba31f2f35586e9b31189 Author: Ralf Jung Date: Tue Sep 5 22:29:51 2023 +0200 fix detecting references to packed unsized fields commit 4cd51770154a0fb0cddd1e94acd34bf7e559f03c Author: Eduardo Sánchez Muñoz Date: Tue Sep 5 20:17:01 2023 +0200 Remove special handling in codegen for some AVX and SSE2 shift by immediate intrinsics Those were removed from stdarch in https://github.com/rust-lang/stdarch/pull/1463 (`simd_shl` and `simd_shr` are used instead) commit 9f562f290dc088c3e24bc7dfb374146ccb48ede8 Author: Eduardo Sánchez Muñoz Date: Tue Sep 5 20:06:50 2023 +0200 Remove special handling in codegen for some SSE2 "storeu" intrinsics Those were removed from stdarch in https://github.com/rust-lang/stdarch/pull/1463 (`<*mut _>::write_unaligned` is used instead) commit 18f36897ef0844dc5e5a0d995356247cbee72ff3 Author: y21 <30553356+y21@users.noreply.github.com> Date: Tue Sep 5 19:08:34 2023 +0200 use the correct node args for substitution commit 71429f5fd2388ff6332889c193409a88c762e7c1 Author: July Tikhonov Date: Tue Sep 5 19:46:18 2023 +0300 fix a comment in std::iter::successors The `unfold` function have since been renamed to `from_fn`. commit 4c2f1c615b976fcd21f6cc2078b09d10c9d72507 Author: Alex Saveau Date: Mon Sep 4 21:43:21 2023 +0100 Weaken needlessly restrictive orderings on Arc::*_count Signed-off-by: Alex Saveau commit d8c1533252e3bab1791a5fffed9dab1cec23c3b9 Author: Tshepang Mbambo Date: Mon Sep 4 17:46:26 2023 +0200 "what would rustfmt do" commit cf10690ad4e1c4df0794fcf072f65515cf8bbadd Author: y21 <30553356+y21@users.noreply.github.com> Date: Mon Aug 7 04:04:51 2023 +0200 check that the receiver type satisfies bounds commit e34e49f7ff8a4fee6667c3ec68a76e2a55e36ad8 Author: y21 <30553356+y21@users.noreply.github.com> Date: Sun Aug 6 23:45:34 2023 +0200 `useless_conversion`: don't lint if ty param has multiple bounds commit a16622f62f10b76af9b61d5177f6e3bb8bdb09b5 Author: Joshua Liebow-Feeser Date: Sun Sep 3 18:12:27 2023 -0700 Clarify ManuallyDrop bit validity Clarify that `ManuallyDrop` has the same bit validity as `T`. commit 1c27ba931b5f5fce58363a59ed7aae94cb4ea336 Author: Michael Watzko Date: Wed Jul 26 22:30:29 2023 +0200 Stabilize the Saturating type (saturating_int_impl, gh-87920) Also stabilizes saturating_int_assign_impl, gh-92354. And also make pub fns const where the underlying saturating_* fns became const in the meantime since the Saturating type was created. commit 26c0f97579763363310bc32cf6d8ef4cd6f5588f Author: y21 <30553356+y21@users.noreply.github.com> Date: Sat Sep 2 21:55:44 2023 +0200 [`len_without_is_empty`]: follow type alias commit dfdab8fc629da55ec434d8838daaba9906a61445 Author: vwkd <33468089+vwkd@users.noreply.github.com> Date: Fri Sep 1 21:58:40 2023 +0200 Update mod.rs commit 1290cd432ddc3bf935cbd1d585b5999a38a103bc Author: Ralf Jung Date: Tue Aug 29 21:08:46 2023 +0200 further expand on Arc and Box analogy commit e7908608d9d11a77b3c73eb1aaac47492575efe9 Author: Chris Denton Date: Mon Aug 28 20:02:40 2023 +0100 Remove old bindings that have been moved commit de3726c9b32c251b3c5181e1dab64f00e68a88c1 Author: Chris Denton Date: Thu Aug 17 15:29:29 2023 +0100 Add GetActiveProcessorCount and process attributes commit eb19bd33bac3f1e5f8cec2ddcb4ad7188baaba1c Author: Chris Denton Date: Wed Aug 16 15:18:53 2023 +0100 Abstract over internal `SOCKET` type This allows `SOCKET` to be `usize` internally commit d9c85daa51bb131696a62a9653debf8ab8d1de07 Author: Chris Denton Date: Wed Aug 16 09:18:34 2023 +0100 Update windows ffi bindings commit 1c77b0b2677f04f535137cdf582c98a281309a1b Author: Alex Macleod Date: Sun Aug 27 11:43:45 2023 +0000 Move needless_raw_string_hashes to pedantic commit fc75f723f681dc2cb1b0be7395c936adfb2f6f63 Author: Ralf Jung Date: Thu Aug 3 12:14:58 2023 +0200 also use 'env' for printing unsetting commit 53a29e0e60b14486fbe06d0d68f311989d693816 Author: Ralf Jung Date: Thu Aug 3 12:07:42 2023 +0200 also print clearing the environment entirely commit 3a28887623fe7c61f7f84759f5d53fbf11f6a55e Author: Ralf Jung Date: Thu Aug 3 12:00:09 2023 +0200 fix a typo in env_clear docs commit 396cbe66397ba77184e4ed896f4ba17f623c00f7 Author: Ralf Jung Date: Thu Aug 3 09:22:54 2023 +0200 make unsetting env vars print as executable command commit f2b139f23d574ca1d2c764b581a3b993e9af1570 Author: Ralf Jung Date: Wed Aug 2 21:20:51 2023 +0200 Command: also print removed env vars commit 2ff14b0050145b79769bf207b7d0bee5c98292b8 Author: Michael Goulet Date: Wed Aug 23 18:25:09 2023 +0000 Remove opinions from style guide about where clauses in type alias items commit adb22b92dd3674cf9b661504575b53245eec7f65 Author: Patiga Date: Sat Dec 3 12:44:32 2022 +0100 Improve UdpSocket documentation I tried working with `UdpSocket` and ran into `EINVAL` errors with no clear indication of what causes the error. Also, it was uncharacteristically hard to figure this module out, compared to other Rust `std` modules. 1. `send` and `send_to` return a `usize` This one is just clarity. Usually, returned `usize`s indicate that the buffer might have only been sent partially. This is not the case with UDP. Since that `usize` must always be `buffer.len()`, I have documented that. 2. `bind` limits `connect` and `send_to` When you bind to a limited address space like localhost, you can only `connect` to addresses in that same address space. Error kind: `AddrNotAvailable`. 3. `connect`ing to localhost locks you to localhost On Linux, if you first `connect` to localhost, subsequent `connect`s to non-localhost addresses fail. Error kind: `InvalidInput`. Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> commit 6d65379e7a5da8f118803bab5618b6c68994ad37 Author: Ralf Jung Date: Tue Aug 22 09:00:07 2023 +0200 clarify what you cannot do commit 2cb9d3def2515e0717f3d8364e83dc2e52ace63c Author: Ralf Jung Date: Tue Aug 22 08:57:38 2023 +0200 typos and wording Co-authored-by: Dan Gohman commit f707b9cd707d84768687caa025d483cef61ed440 Author: Michael Goulet Date: Wed Aug 16 16:41:49 2023 +0000 Describe how to format trailing where clauses commit 85254c9dd8266f24658071b773fbc3ba2da7b35c Author: Michael Goulet Date: Wed Aug 16 16:40:12 2023 +0000 bugfix: reflect how rustfmt formats type aliases commit 72e29da3eccd3e4c1fb2c581fa33216db50fcc93 Author: Be Wilson Date: Mon Jul 3 14:26:05 2023 -0500 stabilize combining +bundle and +whole-archive link modifiers Currently, combining +bundle and +whole-archive works only with #![feature(packed_bundled_libs)] This crate feature is independent of the -Zpacked-bundled-libs command line option. This commit stabilizes the #![feature(packed_bundled_libs)] crate feature and implicitly enables it only when the +bundle and +whole-archive link modifiers are combined. This allows rlib crates to use the +whole-archive link modifier with native libraries and have all symbols included in the linked library to be included in downstream staticlib crates that use the rlib as a dependency. Other cases requiring the packed_bundled_libs behavior still require the -Zpacked-bundled-libs command line option, which can be stabilized independently in the future. Per discussion on https://github.com/rust-lang/rust/issues/108081 there is no risk of regression stabilizing the crate feature in this way because the combination of +bundle,+whole-archive link modifiers was previously not allowed. commit 8ad46b49a29a9a02cf5886051925b31ab5d80c82 Author: Chinedu Francis Nwafili Date: Tue Aug 15 09:41:43 2023 -0400 Misc progress commit 6b58fbfd7ecb7a7ea90065aae0f307f903c0ce54 Author: Esteban Küber Date: Mon Aug 14 21:40:11 2023 +0000 rebase and review comments commit 2c3fd1a23ac04b9a4d44501390d2a207b53d160a Author: Esteban Küber Date: Wed Aug 9 12:31:36 2023 +0000 Suggest `pin!()` instead of `Pin::new()` when appropriate When encountering a type that needs to be pinned but that is `!Unpin`, suggest using the `pin!()` macro. Fix #57994. commit e9eca7cda449490fd818b853068ea21518d19066 Author: Ralf Jung Date: Mon Aug 14 16:53:08 2023 +0200 reference-counting analogy commit 85e6e82f93aa69f57aba3362d8a94199ea4a13db Author: Ralf Jung Date: Mon Aug 14 13:52:21 2023 +0200 reword the paragraph on file description ownership commit 03c28d5626dd1e2077593fe57eff658e15958f0d Author: Ralf Jung Date: Mon Aug 14 13:28:51 2023 +0200 don't link to RFCs, they are not up-to-date docs commit 4da08115132c55289905e9304d202464bd46f059 Author: Ralf Jung Date: Mon Aug 14 09:16:08 2023 +0200 mention /proc/self/fd with /proc/self/mem commit 55f18beddd8a74034a402fae173eb74e046cedaa Author: Ralf Jung Date: Mon Aug 14 08:59:37 2023 +0200 wording; and explain some of the possible consequences of violating io-safety commit 334a54cd83191f38ad8046ed94c45de735c86c65 Author: Ralf Jung Date: Mon Aug 14 08:50:32 2023 +0200 typos commit b2b225e1d1e2bcdd2fabd8765b228b3480f3a998 Author: Ralf Jung Date: Mon Aug 14 08:47:33 2023 +0200 sync the various FromRawFd trait docs, and remove 'valid' commit a473e95786fa2a1391903f2b3b31af5ae300a2d5 Author: Ralf Jung Date: Sun Aug 13 14:36:06 2023 +0200 add more explicit I/O safety documentation commit b56a04975c8c77b14a474fe3b38573872a065971 Author: Chinedu Francis Nwafili Date: Thu Aug 3 09:50:00 2023 -0400 Fix multiple `expect` attribs in impl block Closes #114416 commit 88b99851a2b06be72152e0bc294d46500d17c7ee Author: Jakub Beránek Date: Fri Aug 4 10:40:14 2023 +0200 Print GHA log groups to stdout instead of stderr In all other places (e.g. `bootstrap.py`, `opt-dist`), we use stdout instead of stderr. I think that using stderr might be causing some discrepancies in the log, where sometimes the contents of a group "leak" outside the group. Let's see what happens if we use stdout instead. It's possible that it will be worse, since we print most stuff to stderr (?). commit 6acb415e7c7671c078177a95412987374b30a3c3 Author: Chai T. Rex Date: Thu Aug 3 13:25:52 2023 -0400 Convert `Into for ExitStatusError` to `From for ExitStatus` in `std::process` commit 9baab45e2f2bc3218737613bda074e5b04d2034b Author: Raoul Strackx Date: Mon Jul 31 13:28:44 2023 +0200 Aborting when `before_wait` function panics commit 905f49a72870048688590d8a34b5429cd49efd22 Author: Jethro Beekman Date: Fri Aug 26 16:58:14 2022 +0200 Clean up SGX user memory copies commit 9a5443fe21bfaba77a4c872ec76b8e828bb265c0 Author: Raoul Strackx Date: Mon May 15 15:10:25 2023 +0200 `waitqueue` clarifications for SGX platform commit 40a52cf55cccd497f4e3d04c6b46aecb7f75f467 Author: liushuyu Date: Tue Jul 25 09:48:12 2023 +0800 core library: Disable fpmath tests for i386 ... This patch disables the floating-point epsilon test for i386 since x87 registers are too imprecise and can't produce the expected results. commit b2d35e1f4bc2aa6f2b9745ea515d5d69298b2e52 Author: Nikolai Vazquez Date: Mon Jul 24 21:33:16 2023 -0400 Implement `From<[T; N]>` for `Rc<[T]>` and `Arc<[T]>` commit 27e10e2b5e2a589196c3d72f5da58f480ad14374 Author: EFanZh Date: Sat Jul 15 19:20:41 2023 +0800 Implement `From<{&,&mut} [T; N]>` for `Vec` commit 659c17a6760ca03d3d69e2f44cef8fb3932cec95 Author: Tobias Bucher Date: Fri Jun 23 14:38:30 2023 +0200 Change the wording in `std::fmt::Write::write_str` Refer to the error instead of expanding its name. commit 9de32a7a3b7928b3679118cf423fd69246de8784 Author: Vincent Thiberville Date: Thu Mar 9 10:46:38 2023 +0100 add doc on From impl for ChildStd* commit 7ebbdc6e3b8c8cec8dc78c20f961c4fae415a5a0 Author: Vincent Thiberville Date: Wed Jul 6 15:29:17 2022 +0200 add FromOwnedFd/FromOwnedHandle for ChildStdin/out/err commit 6b98dcc743bd04bc2300655c4e800e6b1dd6f911 Author: tosti007 Date: Wed Mar 29 15:10:35 2023 +0200 Use with_capacity_and_hasher instead of using base commit c953b6c0147557d3775f7cde55f8ffdb2d82bc45 Author: Trevor Spiteri Date: Tue Nov 8 15:52:20 2022 +0100 doc: expand description for f32 and f64 associated constants This explains the meaning of some of the floating-point associated constants. commit 258a65d4a20baa8bf6c9bf1e20e8005e7dae5a7b Author: Tim Vermeulen Date: Sat Aug 20 15:23:16 2022 +0200 Fix generic bound of `SplitInclusive`'s `DoubleEndedIterator` impl --- .github/workflows/ci.yml | 18 +- .mailmap | 2 + .reuse/dep5 | 1 + Cargo.lock | 343 +- README.md | 2 +- RELEASES.md | 117 + compiler/rustc/Cargo.toml | 1 + compiler/rustc_abi/Cargo.toml | 4 +- compiler/rustc_abi/src/layout.rs | 310 +- compiler/rustc_abi/src/lib.rs | 240 +- compiler/rustc_arena/src/lib.rs | 258 +- compiler/rustc_ast/src/entry.rs | 27 + compiler/rustc_ast/src/token.rs | 2 +- compiler/rustc_ast_lowering/messages.ftl | 2 +- compiler/rustc_ast_lowering/src/format.rs | 47 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 7 +- .../rustc_ast_passes/src/ast_validation.rs | 56 +- compiler/rustc_ast_passes/src/feature_gate.rs | 25 +- compiler/rustc_attr/Cargo.toml | 10 +- compiler/rustc_attr/src/builtin.rs | 89 +- .../rustc_attr/src/session_diagnostics.rs | 9 - .../src/diagnostics/conflict_errors.rs | 3 +- .../rustc_borrowck/src/diagnostics/mod.rs | 11 +- .../src/diagnostics/mutability_errors.rs | 5 +- .../src/diagnostics/region_errors.rs | 4 +- .../src/diagnostics/region_name.rs | 10 +- compiler/rustc_borrowck/src/lib.rs | 4 +- .../rustc_borrowck/src/places_conflict.rs | 2 + compiler/rustc_borrowck/src/prefixes.rs | 3 + .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/region_infer/opaque_types.rs | 2 +- compiler/rustc_borrowck/src/renumber.rs | 23 +- compiler/rustc_borrowck/src/type_check/mod.rs | 45 +- .../src/type_check/relate_tys.rs | 9 +- .../rustc_borrowck/src/universal_regions.rs | 31 +- .../src/deriving/bounds.rs | 2 +- .../rustc_builtin_macros/src/test_harness.rs | 22 +- compiler/rustc_codegen_cranelift/Cargo.lock | 166 +- compiler/rustc_codegen_cranelift/Cargo.toml | 16 +- compiler/rustc_codegen_cranelift/Readme.md | 14 +- .../build_system/build_backend.rs | 2 + .../build_system/main.rs | 2 +- .../build_system/prepare.rs | 6 +- .../build_system/tests.rs | 67 +- .../build_system/utils.rs | 35 +- compiler/rustc_codegen_cranelift/config.txt | 1 - .../example/mini_core.rs | 6 + ...ortable-simd-Allow-internal-features.patch | 24 - ...h-gets-miscompiled-with-llvm-sysroot.patch | 25 + ...7-coretests-128bit-atomic-operations.patch | 2 +- .../patches/portable-simd-lock.toml | 72 +- .../patches/rand-lock.toml | 563 ++- .../patches/regex-lock.toml | 422 +- .../patches/stdlib-lock.toml | 28 +- .../rustc_codegen_cranelift/rust-toolchain | 2 +- .../scripts/filter_profile.rs | 6 +- .../scripts/setup_rust_fork.sh | 4 +- .../scripts/test_rustc_tests.sh | 18 +- .../rustc_codegen_cranelift/src/abi/mod.rs | 8 +- .../src/abi/pass_mode.rs | 6 +- .../src/abi/returning.rs | 4 +- .../rustc_codegen_cranelift/src/allocator.rs | 4 +- .../rustc_codegen_cranelift/src/analyze.rs | 4 +- compiler/rustc_codegen_cranelift/src/base.rs | 21 +- compiler/rustc_codegen_cranelift/src/cast.rs | 4 +- .../rustc_codegen_cranelift/src/common.rs | 15 +- .../src/concurrency_limiter.rs | 3 +- .../rustc_codegen_cranelift/src/constant.rs | 14 +- .../src/debuginfo/emit.rs | 3 +- .../src/debuginfo/line_info.rs | 16 +- .../src/debuginfo/mod.rs | 8 +- .../src/debuginfo/object.rs | 7 +- .../src/debuginfo/unwind.rs | 4 +- .../rustc_codegen_cranelift/src/driver/aot.rs | 3 +- .../rustc_codegen_cranelift/src/driver/jit.rs | 3 +- .../rustc_codegen_cranelift/src/global_asm.rs | 23 +- .../rustc_codegen_cranelift/src/inline_asm.rs | 146 +- .../src/intrinsics/llvm.rs | 4 +- .../src/intrinsics/llvm_aarch64.rs | 39 +- .../src/intrinsics/llvm_x86.rs | 10 +- .../src/intrinsics/mod.rs | 7 +- .../src/intrinsics/simd.rs | 87 +- compiler/rustc_codegen_cranelift/src/lib.rs | 39 +- .../rustc_codegen_cranelift/src/pointer.rs | 5 +- .../src/pretty_clif.rs | 22 +- .../src/value_and_place.rs | 14 +- compiler/rustc_codegen_gcc/src/builder.rs | 2 +- compiler/rustc_codegen_gcc/src/lib.rs | 2 +- compiler/rustc_codegen_gcc/test.sh | 2 +- compiler/rustc_codegen_llvm/messages.ftl | 2 + compiler/rustc_codegen_llvm/src/back/lto.rs | 15 +- .../src/back/owned_target_machine.rs | 103 + compiler/rustc_codegen_llvm/src/back/write.rs | 73 +- compiler/rustc_codegen_llvm/src/builder.rs | 14 +- compiler/rustc_codegen_llvm/src/context.rs | 4 +- .../src/coverageinfo/ffi.rs | 46 +- .../src/coverageinfo/map_data.rs | 331 +- .../src/coverageinfo/mapgen.rs | 5 +- .../src/coverageinfo/mod.rs | 45 +- .../src/debuginfo/create_scope_map.rs | 2 +- .../src/debuginfo/metadata.rs | 12 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/errors.rs | 4 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 57 +- compiler/rustc_codegen_llvm/src/lib.rs | 11 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 7 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 6 +- compiler/rustc_codegen_llvm/src/type_.rs | 2 +- compiler/rustc_codegen_ssa/messages.ftl | 4 - compiler/rustc_codegen_ssa/src/back/link.rs | 31 +- compiler/rustc_codegen_ssa/src/back/rpath.rs | 14 +- .../src/back/symbol_export.rs | 10 +- compiler/rustc_codegen_ssa/src/back/write.rs | 9 +- compiler/rustc_codegen_ssa/src/base.rs | 31 +- .../src/debuginfo/type_names.rs | 5 +- compiler/rustc_codegen_ssa/src/errors.rs | 8 - compiler/rustc_codegen_ssa/src/lib.rs | 7 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 17 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 14 +- .../rustc_codegen_ssa/src/mir/constant.rs | 22 +- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 43 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 17 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 23 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 5 +- .../rustc_codegen_ssa/src/traits/backend.rs | 3 +- .../rustc_codegen_ssa/src/traits/builder.rs | 2 +- .../rustc_codegen_ssa/src/traits/type_.rs | 2 +- .../src/const_eval/machine.rs | 6 +- .../rustc_const_eval/src/const_eval/mod.rs | 7 +- .../src/const_eval/valtrees.rs | 3 +- .../rustc_const_eval/src/interpret/cast.rs | 109 +- .../src/interpret/discriminant.rs | 13 +- .../src/interpret/eval_context.rs | 44 +- .../src/interpret/intrinsics.rs | 19 +- .../rustc_const_eval/src/interpret/machine.rs | 6 +- .../rustc_const_eval/src/interpret/memory.rs | 2 +- .../rustc_const_eval/src/interpret/operand.rs | 55 +- .../src/interpret/operator.rs | 147 +- .../rustc_const_eval/src/interpret/place.rs | 29 +- .../src/interpret/projection.rs | 6 +- .../rustc_const_eval/src/interpret/step.rs | 2 +- .../src/interpret/terminator.rs | 23 +- .../rustc_const_eval/src/interpret/util.rs | 5 +- .../src/interpret/validity.rs | 1 - compiler/rustc_const_eval/src/lib.rs | 7 +- .../src/transform/check_consts/check.rs | 13 +- .../src/transform/check_consts/qualifs.rs | 13 +- .../src/transform/promote_consts.rs | 22 +- .../src/transform/validate.rs | 44 +- .../rustc_const_eval/src/util/alignment.rs | 10 +- .../src/util/compare_types.rs | 14 +- compiler/rustc_const_eval/src/util/mod.rs | 2 +- .../rustc_const_eval/src/util/type_name.rs | 3 +- .../rustc_data_structures/src/flock/unix.rs | 24 +- .../src/graph/dominators/mod.rs | 76 +- .../src/graph/dominators/tests.rs | 45 +- compiler/rustc_data_structures/src/lib.rs | 3 +- .../rustc_data_structures/src/profiling.rs | 4 +- .../rustc_data_structures/src/small_c_str.rs | 6 + .../src/sync/worker_local.rs | 8 +- compiler/rustc_driver_impl/src/lib.rs | 31 +- .../src/session_diagnostics.rs | 6 +- .../src/error_codes/E0038.md | 7 +- .../src/error_codes/E0094.md | 4 +- .../src/error_codes/E0211.md | 4 +- .../src/error_codes/E0282.md | 25 +- .../src/error_codes/E0283.md | 46 +- .../src/error_codes/E0551.md | 4 +- .../src/error_codes/E0647.md | 2 +- .../src/error_codes/E0698.md | 4 +- .../src/error_codes/E0760.md | 2 +- compiler/rustc_errors/src/diagnostic.rs | 8 +- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- compiler/rustc_errors/src/lib.rs | 23 +- compiler/rustc_expand/src/config.rs | 162 +- compiler/rustc_feature/src/accepted.rs | 4 + compiler/rustc_feature/src/active.rs | 79 +- compiler/rustc_feature/src/builtin_attrs.rs | 9 +- compiler/rustc_feature/src/lib.rs | 36 +- compiler/rustc_feature/src/removed.rs | 27 +- compiler/rustc_fluent_macro/src/fluent.rs | 58 +- compiler/rustc_hir/src/def.rs | 10 +- compiler/rustc_hir/src/hir.rs | 30 +- compiler/rustc_hir/src/lang_items.rs | 1 - compiler/rustc_hir/src/target.rs | 2 +- compiler/rustc_hir_analysis/messages.ftl | 47 +- .../rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../src/astconv/generics.rs | 17 +- .../rustc_hir_analysis/src/astconv/mod.rs | 33 +- .../rustc_hir_analysis/src/check/check.rs | 171 +- .../src/check/compare_impl_item.rs | 126 +- .../src/check/compare_impl_item/refine.rs | 37 +- .../rustc_hir_analysis/src/check/entry.rs | 60 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 65 +- compiler/rustc_hir_analysis/src/check/mod.rs | 152 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 137 +- .../src/coherence/builtin.rs | 204 +- .../src/coherence/inherent_impls.rs | 1 - .../src/coherence/orphan.rs | 1 - compiler/rustc_hir_analysis/src/collect.rs | 3 +- .../src/collect/generics_of.rs | 7 +- .../src/collect/resolve_bound_vars.rs | 39 +- .../rustc_hir_analysis/src/collect/type_of.rs | 22 + .../src/collect/type_of/opaque.rs | 9 +- compiler/rustc_hir_analysis/src/errors.rs | 124 + .../src/impl_wf_check/min_specialization.rs | 62 +- compiler/rustc_hir_analysis/src/lib.rs | 26 +- .../src/variance/constraints.rs | 16 +- .../rustc_hir_analysis/src/variance/mod.rs | 8 +- .../rustc_hir_analysis/src/variance/terms.rs | 6 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/messages.ftl | 10 - compiler/rustc_hir_typeck/src/_match.rs | 23 +- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/cast.rs | 6 +- compiler/rustc_hir_typeck/src/check.rs | 255 +- compiler/rustc_hir_typeck/src/demand.rs | 141 +- compiler/rustc_hir_typeck/src/errors.rs | 37 +- compiler/rustc_hir_typeck/src/expr.rs | 129 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 10 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 25 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 24 +- .../src/fn_ctxt/suggestions.rs | 65 +- .../drop_ranges/cfg_build.rs | 601 --- .../drop_ranges/cfg_propagate.rs | 92 - .../drop_ranges/cfg_visualize.rs | 96 - .../src/generator_interior/drop_ranges/mod.rs | 306 -- .../drop_ranges/record_consumed_borrow.rs | 242 -- .../src/generator_interior/mod.rs | 711 ---- compiler/rustc_hir_typeck/src/lib.rs | 2 - .../src/mem_categorization.rs | 7 +- .../rustc_hir_typeck/src/method/suggest.rs | 74 +- compiler/rustc_hir_typeck/src/pat.rs | 41 +- compiler/rustc_hir_typeck/src/upvar.rs | 15 + compiler/rustc_hir_typeck/src/writeback.rs | 8 +- .../rustc_incremental/src/assert_dep_graph.rs | 4 +- compiler/rustc_incremental/src/lib.rs | 2 +- .../rustc_incremental/src/persist/load.rs | 132 +- compiler/rustc_incremental/src/persist/mod.rs | 3 +- .../rustc_incremental/src/persist/save.rs | 2 +- compiler/rustc_index/src/bit_set.rs | 8 +- compiler/rustc_infer/messages.ftl | 10 +- compiler/rustc_infer/src/errors/mod.rs | 31 +- .../src/errors/note_and_explain.rs | 7 +- compiler/rustc_infer/src/infer/at.rs | 23 +- .../src/infer/canonical/canonicalizer.rs | 3 +- compiler/rustc_infer/src/infer/equate.rs | 20 - .../src/infer/error_reporting/mod.rs | 538 +-- .../infer/error_reporting/need_type_info.rs | 41 +- .../nice_region_error/named_anon_conflict.rs | 2 +- .../nice_region_error/placeholder_relation.rs | 6 +- .../trait_impl_difference.rs | 6 +- .../infer/error_reporting/note_and_explain.rs | 10 +- compiler/rustc_infer/src/infer/mod.rs | 2 +- .../src/infer/outlives/components.rs | 2 +- .../src/infer/outlives/test_type_match.rs | 24 +- compiler/rustc_infer/src/infer/sub.rs | 19 - compiler/rustc_interface/src/callbacks.rs | 43 +- compiler/rustc_interface/src/interface.rs | 6 +- compiler/rustc_interface/src/lib.rs | 2 +- compiler/rustc_interface/src/passes.rs | 37 +- compiler/rustc_interface/src/queries.rs | 47 +- compiler/rustc_interface/src/tests.rs | 2 - compiler/rustc_lint/messages.ftl | 6 + compiler/rustc_lint/src/array_into_iter.rs | 2 +- compiler/rustc_lint/src/async_fn_in_trait.rs | 128 + compiler/rustc_lint/src/builtin.rs | 15 +- compiler/rustc_lint/src/context.rs | 85 + .../src/deref_into_dyn_supertrait.rs | 2 + compiler/rustc_lint/src/foreign_modules.rs | 7 +- compiler/rustc_lint/src/invalid_from_utf8.rs | 25 +- compiler/rustc_lint/src/lib.rs | 13 +- compiler/rustc_lint/src/lints.rs | 25 + compiler/rustc_lint/src/noop_method_call.rs | 6 + .../src/opaque_hidden_inferred_bound.rs | 10 +- compiler/rustc_lint/src/passes.rs | 156 +- compiler/rustc_lint/src/reference_casting.rs | 165 +- compiler/rustc_lint/src/types.rs | 1 - compiler/rustc_lint_defs/src/builtin.rs | 111 +- compiler/rustc_lint_defs/src/lib.rs | 35 +- compiler/rustc_llvm/Cargo.toml | 4 - .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 32 +- compiler/rustc_log/src/lib.rs | 4 +- compiler/rustc_metadata/src/creader.rs | 5 +- compiler/rustc_metadata/src/lib.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 20 - .../src/rmeta/decoder/cstore_impl.rs | 16 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 51 +- compiler/rustc_metadata/src/rmeta/mod.rs | 9 +- compiler/rustc_metadata/src/rmeta/table.rs | 9 +- compiler/rustc_middle/src/arena.rs | 2 +- .../rustc_middle/src/dep_graph/dep_node.rs | 79 +- compiler/rustc_middle/src/dep_graph/mod.rs | 64 +- compiler/rustc_middle/src/hir/map/mod.rs | 22 +- compiler/rustc_middle/src/hooks/mod.rs | 70 + compiler/rustc_middle/src/infer/canonical.rs | 2 +- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/lint.rs | 9 +- compiler/rustc_middle/src/middle/stability.rs | 6 +- compiler/rustc_middle/src/mir/basic_blocks.rs | 7 +- compiler/rustc_middle/src/mir/consts.rs | 126 +- compiler/rustc_middle/src/mir/coverage.rs | 20 - .../rustc_middle/src/mir/interpret/error.rs | 15 - compiler/rustc_middle/src/mir/mod.rs | 77 +- compiler/rustc_middle/src/mir/patch.rs | 11 +- compiler/rustc_middle/src/mir/pretty.rs | 82 +- compiler/rustc_middle/src/mir/query.rs | 3 +- compiler/rustc_middle/src/mir/statement.rs | 39 +- compiler/rustc_middle/src/mir/syntax.rs | 53 +- compiler/rustc_middle/src/mir/tcx.rs | 11 +- compiler/rustc_middle/src/mir/traversal.rs | 110 +- compiler/rustc_middle/src/mir/visit.rs | 28 +- compiler/rustc_middle/src/query/erase.rs | 8 +- compiler/rustc_middle/src/query/keys.rs | 33 - compiler/rustc_middle/src/query/mod.rs | 30 +- compiler/rustc_middle/src/query/plumbing.rs | 8 +- compiler/rustc_middle/src/thir.rs | 26 +- compiler/rustc_middle/src/thir/visit.rs | 6 +- compiler/rustc_middle/src/traits/mod.rs | 7 + .../rustc_middle/src/traits/solve/inspect.rs | 66 +- .../src/traits/solve/inspect/format.rs | 2 +- compiler/rustc_middle/src/ty/_match.rs | 12 +- compiler/rustc_middle/src/ty/adt.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 15 +- compiler/rustc_middle/src/ty/consts.rs | 17 +- compiler/rustc_middle/src/ty/context.rs | 42 +- compiler/rustc_middle/src/ty/diagnostics.rs | 4 +- compiler/rustc_middle/src/ty/error.rs | 5 +- compiler/rustc_middle/src/ty/fast_reject.rs | 13 +- compiler/rustc_middle/src/ty/flags.rs | 6 +- compiler/rustc_middle/src/ty/fold.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 21 +- compiler/rustc_middle/src/ty/layout.rs | 1 - compiler/rustc_middle/src/ty/mod.rs | 68 +- .../src/ty/normalize_erasing_regions.rs | 24 +- compiler/rustc_middle/src/ty/opaque_types.rs | 4 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 3 +- compiler/rustc_middle/src/ty/print/pretty.rs | 29 +- compiler/rustc_middle/src/ty/relate.rs | 14 +- .../rustc_middle/src/ty/structural_impls.rs | 11 +- compiler/rustc_middle/src/ty/sty.rs | 37 +- .../rustc_middle/src/ty/typeck_results.rs | 70 - compiler/rustc_middle/src/ty/util.rs | 24 +- compiler/rustc_middle/src/ty/walk.rs | 5 +- .../rustc_middle/src/util/find_self_call.rs | 4 +- compiler/rustc_middle/src/util/mod.rs | 24 + compiler/rustc_middle/src/values.rs | 74 +- compiler/rustc_mir_build/messages.ftl | 3 + compiler/rustc_mir_build/src/build/cfg.rs | 6 +- .../src/build/custom/parse/instruction.rs | 10 +- .../src/build/expr/as_constant.rs | 56 +- .../src/build/expr/as_place.rs | 3 +- .../src/build/expr/as_rvalue.rs | 12 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 2 - .../rustc_mir_build/src/build/expr/into.rs | 24 +- .../rustc_mir_build/src/build/expr/mod.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 11 +- .../rustc_mir_build/src/build/matches/test.rs | 29 +- compiler/rustc_mir_build/src/build/misc.rs | 18 +- compiler/rustc_mir_build/src/build/mod.rs | 4 +- compiler/rustc_mir_build/src/build/scope.rs | 2 +- compiler/rustc_mir_build/src/errors.rs | 6 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 14 +- .../src/thir/pattern/check_match.rs | 4 +- .../src/thir/pattern/const_to_pat.rs | 87 +- .../src/thir/pattern/deconstruct_pat.rs | 248 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 48 +- compiler/rustc_mir_dataflow/src/debuginfo.rs | 20 + .../rustc_mir_dataflow/src/elaborate_drops.rs | 11 +- compiler/rustc_mir_dataflow/src/lib.rs | 1 + .../src/move_paths/abs_domain.rs | 1 + .../src/move_paths/builder.rs | 146 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- .../rustc_mir_dataflow/src/value_analysis.rs | 8 +- .../src/add_subtyping_projections.rs | 70 + .../src/check_alignment.rs | 14 +- .../rustc_mir_transform/src/check_unsafety.rs | 8 +- .../src/const_debuginfo.rs | 4 +- .../rustc_mir_transform/src/const_goto.rs | 4 +- .../rustc_mir_transform/src/const_prop.rs | 10 +- .../src/const_prop_lint.rs | 10 +- .../src/coverage/counters.rs | 37 +- .../rustc_mir_transform/src/coverage/graph.rs | 4 +- .../rustc_mir_transform/src/coverage/mod.rs | 81 +- .../rustc_mir_transform/src/coverage/query.rs | 4 +- .../rustc_mir_transform/src/coverage/spans.rs | 59 +- .../rustc_mir_transform/src/coverage/tests.rs | 34 +- .../src/dataflow_const_prop.rs | 46 +- .../src/dead_store_elimination.rs | 22 +- .../src/deduplicate_blocks.rs | 8 +- .../src/deref_separator.rs | 2 +- .../src/elaborate_box_derefs.rs | 2 +- .../src/elaborate_drops.rs | 7 +- compiler/rustc_mir_transform/src/errors.rs | 34 +- compiler/rustc_mir_transform/src/generator.rs | 116 +- compiler/rustc_mir_transform/src/gvn.rs | 539 +++ compiler/rustc_mir_transform/src/inline.rs | 59 +- .../rustc_mir_transform/src/inline/cycle.rs | 2 +- .../rustc_mir_transform/src/instsimplify.rs | 6 +- .../rustc_mir_transform/src/large_enums.rs | 11 +- compiler/rustc_mir_transform/src/lib.rs | 31 +- .../src/lower_intrinsics.rs | 29 +- .../src/lower_slice_len.rs | 79 +- .../rustc_mir_transform/src/match_branches.rs | 12 +- .../src/normalize_array_len.rs | 4 +- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../rustc_mir_transform/src/remove_zsts.rs | 6 +- .../src/required_consts.rs | 18 +- .../rustc_mir_transform/src/reveal_all.rs | 40 +- compiler/rustc_mir_transform/src/shim.rs | 8 +- compiler/rustc_mir_transform/src/simplify.rs | 53 +- .../src/simplify_branches.rs | 4 +- .../src/simplify_comparison_integral.rs | 4 +- compiler/rustc_mir_transform/src/ssa.rs | 126 +- .../src/uninhabited_enum_branching.rs | 25 +- .../src/unreachable_prop.rs | 6 +- compiler/rustc_monomorphize/messages.ftl | 2 - compiler/rustc_monomorphize/src/collector.rs | 157 +- .../rustc_monomorphize/src/partitioning.rs | 2 +- .../rustc_monomorphize/src/polymorphize.rs | 18 +- compiler/rustc_monomorphize/src/util.rs | 4 +- compiler/rustc_parse/messages.ftl | 36 +- compiler/rustc_parse/src/errors.rs | 24 +- .../rustc_parse/src/parser/diagnostics.rs | 7 +- compiler/rustc_parse/src/parser/expr.rs | 92 +- compiler/rustc_parse/src/parser/item.rs | 7 +- compiler/rustc_parse/src/parser/mod.rs | 1 + compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_passes/messages.ftl | 10 + compiler/rustc_passes/src/abi_test.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 65 +- compiler/rustc_passes/src/check_const.rs | 4 +- compiler/rustc_passes/src/dead.rs | 77 +- compiler/rustc_passes/src/entry.rs | 33 +- compiler/rustc_passes/src/errors.rs | 29 + compiler/rustc_passes/src/lang_items.rs | 12 +- compiler/rustc_passes/src/layout_test.rs | 4 +- compiler/rustc_passes/src/loops.rs | 55 +- compiler/rustc_privacy/src/lib.rs | 9 +- compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_query_impl/src/lib.rs | 6 +- compiler/rustc_query_impl/src/plumbing.rs | 37 +- compiler/rustc_query_system/messages.ftl | 2 - .../rustc_query_system/src/dep_graph/debug.rs | 14 +- .../src/dep_graph/dep_node.rs | 92 +- .../rustc_query_system/src/dep_graph/graph.rs | 163 +- .../rustc_query_system/src/dep_graph/mod.rs | 84 +- .../rustc_query_system/src/dep_graph/query.rs | 22 +- .../src/dep_graph/serialized.rs | 107 +- .../rustc_query_system/src/query/config.rs | 10 +- compiler/rustc_query_system/src/query/job.rs | 117 +- compiler/rustc_query_system/src/query/mod.rs | 10 +- .../rustc_query_system/src/query/plumbing.rs | 74 +- compiler/rustc_query_system/src/values.rs | 10 +- compiler/rustc_resolve/messages.ftl | 12 - .../rustc_resolve/src/build_reduced_graph.rs | 7 +- compiler/rustc_resolve/src/diagnostics.rs | 8 +- compiler/rustc_resolve/src/late.rs | 64 +- .../rustc_resolve/src/late/diagnostics.rs | 142 +- compiler/rustc_resolve/src/lib.rs | 11 +- compiler/rustc_resolve/src/macros.rs | 2 +- .../rustc_serialize/src/collection_impls.rs | 279 -- compiler/rustc_serialize/src/lib.rs | 17 +- compiler/rustc_serialize/src/opaque.rs | 7 +- compiler/rustc_serialize/src/serialize.rs | 262 +- compiler/rustc_session/messages.ftl | 2 - compiler/rustc_session/src/config.rs | 21 +- compiler/rustc_session/src/options.rs | 43 +- compiler/rustc_session/src/session.rs | 9 + compiler/rustc_session/src/utils.rs | 9 + compiler/rustc_smir/Cargo.toml | 25 +- compiler/rustc_smir/src/lib.rs | 18 - compiler/rustc_smir/src/rustc_internal/mod.rs | 99 +- compiler/rustc_smir/src/rustc_smir/alloc.rs | 8 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 320 +- compiler/rustc_span/src/lib.rs | 16 +- compiler/rustc_span/src/symbol.rs | 52 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 12 +- compiler/rustc_symbol_mangling/src/v0.rs | 7 +- compiler/rustc_target/Cargo.toml | 1 + compiler/rustc_target/src/abi/mod.rs | 110 +- compiler/rustc_target/src/spec/apple_base.rs | 56 +- .../rustc_target/src/spec/armv7_apple_ios.rs | 21 - .../rustc_target/src/spec/armv7s_apple_ios.rs | 4 +- compiler/rustc_target/src/spec/hurd_base.rs | 15 + .../rustc_target/src/spec/hurd_gnu_base.rs | 5 + .../src/spec/i686_unknown_hurd_gnu.rs | 19 + compiler/rustc_target/src/spec/mod.rs | 20 +- .../src/spec/riscv64_linux_android.rs | 2 +- .../src/spec/thumbv7neon_linux_androideabi.rs | 2 +- .../thumbv7neon_unknown_linux_gnueabihf.rs | 2 +- .../thumbv7neon_unknown_linux_musleabihf.rs | 2 +- .../rustc_target/src/spec/uefi_msvc_base.rs | 1 + .../src/spec/x86_64_apple_darwin.rs | 2 +- .../src/spec/x86_64_unknown_uefi.rs | 3 +- .../src/solve/assembly/mod.rs | 8 +- .../src/solve/assembly/structural_traits.rs | 17 +- .../src/solve/canonicalize.rs | 5 +- .../src/solve/eval_ctxt.rs | 9 +- .../src/solve/eval_ctxt/canonical.rs | 97 +- .../src/solve/inspect/analyse.rs | 235 ++ .../solve/{inspect.rs => inspect/build.rs} | 238 +- .../src/solve/inspect/mod.rs | 7 + .../rustc_trait_selection/src/solve/mod.rs | 2 +- .../src/solve/project_goals.rs | 13 +- .../src/solve/search_graph/cache.rs | 102 - .../src/solve/search_graph/mod.rs | 152 +- .../src/solve/trait_goals.rs | 3 +- .../src/traits/coherence.rs | 224 +- .../src/traits/engine.rs | 17 +- .../traits/error_reporting/infer_ctxt_ext.rs | 275 ++ .../src/traits/error_reporting/mod.rs | 3402 +---------------- .../error_reporting/on_unimplemented.rs | 8 +- .../src/traits/error_reporting/suggestions.rs | 464 +-- .../error_reporting/type_err_ctxt_ext.rs | 3241 ++++++++++++++++ .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/project.rs | 4 +- .../src/traits/query/dropck_outlives.rs | 4 +- .../src/traits/select/candidate_assembly.rs | 13 +- .../src/traits/select/confirmation.rs | 5 +- .../src/traits/select/mod.rs | 71 +- .../src/traits/structural_match.rs | 2 +- .../src/traits/structural_normalize.rs | 12 +- .../src/traits/vtable.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 53 +- compiler/rustc_transmute/src/lib.rs | 4 +- .../src/maybe_transmutable/mod.rs | 110 +- compiler/rustc_ty_utils/src/abi.rs | 2 +- compiler/rustc_ty_utils/src/consts.rs | 2 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 4 +- compiler/rustc_ty_utils/src/layout.rs | 8 +- compiler/rustc_ty_utils/src/needs_drop.rs | 28 +- compiler/rustc_ty_utils/src/opaque_types.rs | 8 +- compiler/rustc_ty_utils/src/ty.rs | 24 +- compiler/rustc_type_ir/src/sty.rs | 90 +- compiler/stable_mir/Cargo.toml | 8 + compiler/{rustc_smir => stable_mir}/README.md | 0 .../rust-toolchain.toml | 0 .../src/stable_mir => stable_mir/src}/fold.rs | 31 +- .../mod.rs => stable_mir/src/lib.rs} | 86 +- .../src/stable_mir => stable_mir/src}/mir.rs | 0 .../stable_mir => stable_mir/src}/mir/body.rs | 46 +- .../src/stable_mir => stable_mir/src}/ty.rs | 85 +- .../stable_mir => stable_mir/src}/visitor.rs | 22 +- config.example.toml | 17 +- library/alloc/src/borrow.rs | 1 + .../collections/btree/dedup_sorted_iter.rs | 2 +- library/alloc/src/lib.rs | 1 + library/alloc/src/rc.rs | 26 +- library/alloc/src/string.rs | 1 + library/alloc/src/sync.rs | 34 +- library/alloc/src/vec/mod.rs | 30 + library/alloc/tests/vec.rs | 10 + library/core/src/array/iter.rs | 1 + library/core/src/cell.rs | 2 + library/core/src/cmp.rs | 74 +- library/core/src/convert/mod.rs | 42 + library/core/src/default.rs | 1 + library/core/src/fmt/builders.rs | 1 + library/core/src/fmt/mod.rs | 11 +- library/core/src/fmt/rt.rs | 4 + library/core/src/hint.rs | 2 +- library/core/src/intrinsics.rs | 5 + library/core/src/iter/adapters/peekable.rs | 1 + library/core/src/iter/sources/empty.rs | 1 + library/core/src/iter/sources/once.rs | 1 + library/core/src/iter/sources/successors.rs | 2 +- library/core/src/iter/traits/collect.rs | 1 + library/core/src/lib.rs | 4 + library/core/src/macros/mod.rs | 123 +- library/core/src/marker.rs | 7 +- library/core/src/mem/manually_drop.rs | 12 +- library/core/src/mem/mod.rs | 12 +- library/core/src/num/f32.rs | 44 +- library/core/src/num/f64.rs | 42 +- library/core/src/num/int_macros.rs | 54 + library/core/src/num/uint_macros.rs | 64 + library/core/src/ops/deref.rs | 1 + library/core/src/ops/drop.rs | 2 +- library/core/src/ops/function.rs | 6 +- library/core/src/ops/range.rs | 1 + library/core/src/option.rs | 22 +- library/core/src/panic.rs | 45 + library/core/src/panicking.rs | 15 +- library/core/src/pin.rs | 5 +- library/core/src/primitive_docs.rs | 10 +- library/core/src/ptr/const_ptr.rs | 23 +- library/core/src/ptr/mod.rs | 34 + library/core/src/ptr/mut_ptr.rs | 23 +- library/core/src/ptr/non_null.rs | 1 + library/core/src/result.rs | 1 + library/core/src/slice/iter.rs | 1 + library/core/src/slice/mod.rs | 2 +- library/core/src/slice/raw.rs | 2 + library/core/src/str/iter.rs | 2 +- library/core/src/str/mod.rs | 2 +- library/core/src/str/traits.rs | 1 + library/core/src/sync/exclusive.rs | 46 +- library/core/src/time.rs | 9 + library/core/tests/array.rs | 4 +- library/core/tests/lib.rs | 3 + library/core/tests/macros.rs | 154 + library/core/tests/num/int_macros.rs | 32 + library/core/tests/num/uint_macros.rs | 29 + library/panic_abort/src/lib.rs | 3 +- library/proc_macro/src/lib.rs | 17 +- library/std/Cargo.toml | 8 + library/std/build.rs | 12 +- library/std/src/collections/hash/set.rs | 2 +- library/std/src/fs.rs | 3 + library/std/src/io/error.rs | 8 +- library/std/src/io/mod.rs | 85 +- library/std/src/io/stdio.rs | 2 + library/std/src/lib.rs | 7 +- library/std/src/net/udp.rs | 21 +- library/std/src/os/aix/fs.rs | 348 ++ library/std/src/os/aix/mod.rs | 6 + library/std/src/os/aix/raw.rs | 9 + library/std/src/os/fd/owned.rs | 12 +- library/std/src/os/fd/raw.rs | 5 +- library/std/src/os/fortanix_sgx/io.rs | 23 +- library/std/src/os/hurd/fs.rs | 348 ++ library/std/src/os/hurd/mod.rs | 6 + library/std/src/os/hurd/raw.rs | 33 + library/std/src/os/mod.rs | 6 + library/std/src/os/solid/io.rs | 22 +- library/std/src/os/uefi/env.rs | 92 + library/std/src/os/uefi/mod.rs | 8 + library/std/src/os/unix/io/mod.rs | 16 +- library/std/src/os/unix/mod.rs | 4 + library/std/src/os/unix/process.rs | 42 + library/std/src/os/windows/io/mod.rs | 10 +- library/std/src/os/windows/io/raw.rs | 6 +- library/std/src/os/windows/io/socket.rs | 8 +- library/std/src/os/windows/process.rs | 39 + library/std/src/process.rs | 154 +- library/std/src/process/tests.rs | 47 +- library/std/src/sync/once.rs | 2 +- library/std/src/sync/rwlock.rs | 4 +- .../std/src/sys/common/thread_local/mod.rs | 2 +- library/std/src/sys/mod.rs | 4 + library/std/src/sys/personality/gcc.rs | 2 +- .../std/src/sys/sgx/abi/usercalls/alloc.rs | 207 +- library/std/src/sys/sgx/waitqueue/mod.rs | 26 +- library/std/src/sys/uefi/alloc.rs | 33 + library/std/src/sys/uefi/env.rs | 9 + library/std/src/sys/uefi/helpers.rs | 141 + library/std/src/sys/uefi/mod.rs | 243 ++ library/std/src/sys/uefi/os.rs | 237 ++ library/std/src/sys/uefi/path.rs | 25 + library/std/src/sys/uefi/stdio.rs | 162 + library/std/src/sys/uefi/tests.rs | 21 + library/std/src/sys/unix/args.rs | 2 + library/std/src/sys/unix/env.rs | 22 + library/std/src/sys/unix/fd.rs | 18 +- library/std/src/sys/unix/fs.rs | 96 +- library/std/src/sys/unix/kernel_copy.rs | 4 +- library/std/src/sys/unix/mod.rs | 5 + library/std/src/sys/unix/net.rs | 3 + library/std/src/sys/unix/os.rs | 51 +- library/std/src/sys/unix/pipe.rs | 9 +- .../src/sys/unix/process/process_common.rs | 17 + .../std/src/sys/unix/process/process_unix.rs | 13 + library/std/src/sys/unix/stack_overflow.rs | 2 + library/std/src/sys/unix/thread.rs | 37 +- library/std/src/sys/unix/thread_local_dtor.rs | 54 +- .../std/src/sys/unix/thread_parking/darwin.rs | 3 +- library/std/src/sys/unix/time.rs | 2 +- library/std/src/sys/wasi/mod.rs | 115 +- library/std/src/sys/windows/c.rs | 8 +- library/std/src/sys/windows/c/windows_sys.lst | 16 +- library/std/src/sys/windows/c/windows_sys.rs | 164 +- library/std/src/sys/windows/cmath.rs | 6 +- library/std/src/sys/windows/fs.rs | 8 +- library/std/src/sys/windows/handle.rs | 9 +- library/std/src/sys/windows/io.rs | 4 +- library/std/src/sys/windows/net.rs | 40 +- library/std/src/sys/windows/pipe.rs | 8 +- library/std/src/sys/windows/process.rs | 5 +- library/std/src/sys/windows/thread.rs | 2 +- library/std/src/sys_common/mod.rs | 1 + library/std/src/sys_common/net.rs | 1 + library/std/src/sys_common/process.rs | 4 + library/std/src/time.rs | 3 + library/stdarch | 2 +- library/unwind/src/lib.rs | 8 + rust-bors.toml | 1 + src/bootstrap/CHANGELOG.md | 71 - src/bootstrap/README.md | 14 +- src/bootstrap/bin/main.rs | 41 +- src/bootstrap/bootstrap.py | 107 +- src/bootstrap/bootstrap_test.py | 2 +- src/bootstrap/compile.rs | 34 +- src/bootstrap/config.rs | 26 +- src/bootstrap/config/tests.rs | 12 +- src/bootstrap/dist.rs | 13 +- src/bootstrap/install.rs | 31 + src/bootstrap/lib.rs | 27 +- src/bootstrap/llvm.rs | 9 +- src/bootstrap/mk/Makefile.in | 7 + src/bootstrap/setup.rs | 5 +- src/ci/docker/README.md | 4 +- .../dist-loongarch64-linux/Dockerfile | 5 +- .../host-x86_64/dist-various-1/Dockerfile | 47 +- .../dist-various-1/install-mips-musl.sh | 15 - .../dist-various-1/install-mipsel-musl.sh | 15 - .../host-x86_64/dist-various-2/Dockerfile | 2 + .../host-x86_64/dist-x86_64-linux/Dockerfile | 3 +- .../dist-x86_64-linux/build-clang.sh | 2 +- src/ci/docker/host-x86_64/wasm32/Dockerfile | 63 - src/ci/docker/run.sh | 6 + src/ci/docker/scripts/crosstool-ng-git.sh | 17 - src/ci/docker/scripts/crosstool-ng.sh | 2 +- src/ci/github-actions/ci.yml | 14 +- src/ci/run.sh | 3 +- src/ci/scripts/setup-environment.sh | 2 +- src/ci/scripts/verify-channel.sh | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rustc-dev-guide | 2 +- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/codegen-options/index.md | 8 +- src/doc/rustc/src/platform-support.md | 69 +- .../platform-support/aarch64-unknown-teeos.md | 2 +- src/doc/rustc/src/platform-support/hurd.md | 35 + .../src/platform-support/loongarch-none.md | 2 +- .../src/platform-support/mips-release-6.md | 2 +- src/doc/rustc/src/platform-support/nto-qnx.md | 2 +- .../rustc/src/platform-support/openharmony.md | 2 +- .../src/platform-support/unknown-uefi.md | 83 +- src/doc/rustdoc/src/unstable-features.md | 2 +- src/doc/style-guide/src/items.md | 38 +- .../compiler-flags/link-native-libraries.md | 8 + .../src/compiler-flags/sanitizer.md | 161 +- .../src/language-features/lang-items.md | 2 +- .../src/language-features/plugin.md | 12 +- src/etc/installer/pkg/Distribution.xml | 2 +- src/librustdoc/clean/auto_trait.rs | 7 +- src/librustdoc/clean/inline.rs | 19 +- src/librustdoc/clean/mod.rs | 146 +- src/librustdoc/clean/simplify.rs | 19 +- src/librustdoc/clean/types.rs | 91 +- src/librustdoc/clean/utils.rs | 36 +- src/librustdoc/core.rs | 2 +- src/librustdoc/doctest.rs | 2 +- src/librustdoc/formats/item_type.rs | 2 +- src/librustdoc/html/format.rs | 5 +- src/librustdoc/html/markdown.rs | 2 +- src/librustdoc/html/render/print_item.rs | 106 +- src/librustdoc/html/static/js/search.js | 2 +- .../html/templates/type_layout.html | 4 +- src/librustdoc/json/conversions.rs | 7 +- src/librustdoc/lib.rs | 7 - .../passes/collect_intra_doc_links.rs | 5 +- src/llvm-project | 2 +- src/tools/build-manifest/src/main.rs | 3 +- src/tools/build_helper/src/ci.rs | 6 +- src/tools/cargo | 2 +- src/tools/clippy/.github/workflows/remark.yml | 8 +- src/tools/clippy/CHANGELOG.md | 102 +- src/tools/clippy/Cargo.toml | 5 +- .../book/src/development/adding_lints.md | 2 +- .../clippy/book/src/lint_configuration.md | 15 +- src/tools/clippy/clippy_dev/src/new_lint.rs | 63 +- src/tools/clippy/clippy_lints/Cargo.toml | 5 +- .../clippy_lints/src/allow_attributes.rs | 2 +- src/tools/clippy/clippy_lints/src/attrs.rs | 6 +- .../clippy_lints/src/await_holding_invalid.rs | 45 +- .../clippy/clippy_lints/src/box_default.rs | 14 +- .../clippy_lints/src/casts/cast_lossless.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 2 +- .../src/casts/cast_ptr_alignment.rs | 19 +- .../src/casts/cast_slice_from_raw_parts.rs | 12 +- .../clippy/clippy_lints/src/casts/mod.rs | 26 + .../clippy/clippy_lints/src/casts/zero_ptr.rs | 39 + .../clippy/clippy_lints/src/create_dir.rs | 4 +- .../clippy/clippy_lints/src/declared_lints.rs | 9 +- src/tools/clippy/clippy_lints/src/default.rs | 10 +- .../src/default_constructed_unit_structs.rs | 5 +- .../src/default_instead_of_iter_empty.rs | 6 +- .../src/default_union_representation.rs | 22 +- .../clippy/clippy_lints/src/dereference.rs | 375 +- src/tools/clippy/clippy_lints/src/doc.rs | 3 +- .../clippy/clippy_lints/src/enum_clike.rs | 6 +- .../clippy/clippy_lints/src/enum_variants.rs | 5 +- .../clippy_lints/src/error_impl_error.rs | 10 +- src/tools/clippy/clippy_lints/src/exit.rs | 5 +- .../clippy/clippy_lints/src/explicit_write.rs | 102 +- .../src/extra_unused_type_parameters.rs | 7 +- src/tools/clippy/clippy_lints/src/format.rs | 14 +- .../clippy/clippy_lints/src/format_args.rs | 20 +- .../clippy/clippy_lints/src/format_impl.rs | 41 +- .../clippy_lints/src/four_forward_slashes.rs | 2 +- .../src/from_raw_with_void_ptr.rs | 4 +- .../clippy_lints/src/ignored_unit_patterns.rs | 4 + .../clippy_lints/src/implicit_hasher.rs | 5 +- .../clippy_lints/src/init_numbered_fields.rs | 2 +- .../clippy_lints/src/instant_subtraction.rs | 6 +- .../src/items_after_test_module.rs | 108 +- .../src/iter_without_into_iter.rs | 249 ++ .../clippy_lints/src/large_const_arrays.rs | 5 +- .../clippy/clippy_lints/src/large_futures.rs | 18 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 8 + src/tools/clippy/clippy_lints/src/lib.rs | 25 +- .../clippy_lints/src/lines_filter_map_ok.rs | 4 +- .../clippy/clippy_lints/src/loops/utils.rs | 3 +- .../clippy_lints/src/manual_float_methods.rs | 6 +- .../clippy_lints/src/manual_hash_one.rs | 133 + .../clippy_lints/src/manual_let_else.rs | 4 +- .../clippy_lints/src/manual_non_exhaustive.rs | 22 +- .../clippy/clippy_lints/src/manual_retain.rs | 2 +- .../clippy/clippy_lints/src/matches/mod.rs | 2 +- .../src/matches/needless_match.rs | 17 +- .../src/matches/overlapping_arms.rs | 6 +- .../src/matches/redundant_guards.rs | 101 +- .../clippy_lints/src/methods/bytecount.rs | 8 +- .../src/methods/clone_on_ref_ptr.rs | 19 +- .../src/methods/expect_fun_call.rs | 13 +- .../src/methods/filter_map_bool_then.rs | 11 +- .../methods/from_iter_instead_of_collect.rs | 4 +- .../src/methods/inefficient_to_string.rs | 3 +- .../src/methods/iter_out_of_bounds.rs | 10 +- .../clippy/clippy_lints/src/methods/mod.rs | 102 +- .../clippy_lints/src/methods/open_options.rs | 8 +- .../src/methods/option_as_ref_deref.rs | 5 +- .../src/methods/path_ends_with_ext.rs | 53 + .../src/methods/redundant_as_str.rs | 34 + .../src/methods/seek_from_current.rs | 5 +- .../seek_to_start_instead_of_rewind.rs | 6 +- .../methods/suspicious_command_arg_space.rs | 7 +- .../src/methods/unnecessary_literal_unwrap.rs | 15 +- .../src/methods/unnecessary_to_owned.rs | 4 +- src/tools/clippy/clippy_lints/src/misc.rs | 176 +- .../src/missing_assert_message.rs | 4 + .../clippy_lints/src/missing_const_for_fn.rs | 12 +- .../src/missing_fields_in_debug.rs | 12 +- .../src/mixed_read_write_in_expression.rs | 20 +- .../src/needless_borrows_for_generic_args.rs | 410 ++ .../src/needless_pass_by_ref_mut.rs | 75 +- .../src/needless_pass_by_value.rs | 4 +- .../clippy/clippy_lints/src/no_effect.rs | 11 +- .../clippy_lints/src/non_canonical_impls.rs | 27 +- .../clippy/clippy_lints/src/non_copy_const.rs | 15 +- .../src/non_octal_unix_permissions.rs | 10 +- .../src/non_send_fields_in_send_ty.rs | 4 +- .../src/operators/arithmetic_side_effects.rs | 2 +- .../clippy_lints/src/operators/cmp_owned.rs | 4 +- .../clippy/clippy_lints/src/operators/mod.rs | 4 +- .../src/operators/numeric_arithmetic.rs | 2 +- .../src/permissions_set_readonly_false.rs | 6 +- src/tools/clippy/clippy_lints/src/ptr.rs | 115 +- .../clippy/clippy_lints/src/raw_strings.rs | 37 +- .../clippy_lints/src/rc_clone_in_vec_init.rs | 9 +- .../clippy_lints/src/redundant_clone.rs | 4 +- .../src/redundant_closure_call.rs | 7 +- .../clippy_lints/src/redundant_locals.rs | 36 +- .../src/size_of_in_element_count.rs | 22 +- .../clippy_lints/src/std_instead_of_core.rs | 6 +- .../clippy_lints/src/swap_ptr_to_ref.rs | 6 +- .../src/transmute/transmute_null_to_fn.rs | 30 +- .../clippy/clippy_lints/src/types/mod.rs | 11 +- .../src/unit_types/let_unit_value.rs | 3 +- .../clippy_lints/src/unnamed_address.rs | 4 +- .../src/unnecessary_map_on_constructor.rs | 93 + .../clippy_lints/src/unused_peekable.rs | 10 +- .../clippy_lints/src/useless_conversion.rs | 114 +- .../clippy/clippy_lints/src/utils/conf.rs | 52 +- .../src/utils/format_args_collector.rs | 28 +- .../interning_defined_symbol.rs | 2 +- .../src/utils/internal_lints/invalid_paths.rs | 18 +- .../internal_lints/lint_without_lint_pass.rs | 4 +- .../internal_lints/metadata_collector.rs | 37 +- .../utils/internal_lints/msrv_attr_impl.rs | 15 +- .../internal_lints/unnecessary_def_path.rs | 6 +- .../clippy_lints/src/wildcard_imports.rs | 1 + src/tools/clippy/clippy_lints/src/write.rs | 152 +- src/tools/clippy/clippy_utils/Cargo.toml | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 84 +- src/tools/clippy/clippy_utils/src/higher.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 70 +- src/tools/clippy/clippy_utils/src/macros.rs | 51 +- src/tools/clippy/clippy_utils/src/mir/mod.rs | 72 +- src/tools/clippy/clippy_utils/src/msrvs.rs | 2 +- src/tools/clippy/clippy_utils/src/paths.rs | 48 - .../clippy_utils/src/qualify_min_const_fn.rs | 1 + src/tools/clippy/clippy_utils/src/ty.rs | 9 +- .../clippy_utils/src/ty/type_certainty/mod.rs | 15 +- src/tools/clippy/clippy_utils/src/visitors.rs | 44 + .../clippy/declare_clippy_lint/Cargo.toml | 2 +- src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/src/driver.rs | 55 +- src/tools/clippy/src/main.rs | 63 +- src/tools/clippy/tests/compile-test.rs | 2 - .../unnecessary_def_path_hardcoded_path.rs | 4 +- ...unnecessary_def_path_hardcoded_path.stderr | 4 +- .../await_holding_invalid_type.rs | 6 +- .../await_holding_invalid_type.stderr | 6 +- .../clippy.toml | 1 + .../decimal_literal_representation.fixed | 6 + .../decimal_literal_representation.rs | 6 + .../decimal_literal_representation.stderr | 11 + .../disallowed_script_idents/clippy.toml | 1 + .../disallowed_script_idents.rs | 6 + .../disallowed_script_idents.stderr | 11 + .../ui-toml/enum_variant_names/clippy.toml | 1 + .../enum_variant_names/enum_variant_names.rs | 16 + .../enum_variant_names.stderr | 18 + .../ui-toml/enum_variant_size/clippy.toml | 1 + .../enum_variant_size/enum_variant_size.fixed | 11 + .../enum_variant_size/enum_variant_size.rs | 11 + .../enum_variant_size.stderr | 21 + .../enum_variants_threshold0/clippy.toml | 1 + .../enum_variants_name_threshold.rs | 3 + .../ui-toml/explicit_iter_loop/clippy.toml | 1 + .../explicit_iter_loop.fixed | 10 + .../explicit_iter_loop/explicit_iter_loop.rs | 10 + .../explicit_iter_loop.stderr | 17 + .../ui-toml/large_stack_frames/clippy.toml | 1 + .../large_stack_frames/large_stack_frames.rs | 17 + .../large_stack_frames.stderr | 15 + .../large_types_passed_by_value/clippy.toml | 1 + .../large_types_passed_by_value.fixed | 7 + .../large_types_passed_by_value.rs | 7 + .../large_types_passed_by_value.stderr | 11 + .../tests/ui-toml/manual_let_else/clippy.toml | 1 + .../manual_let_else/manual_let_else.fixed | 10 + .../manual_let_else/manual_let_else.rs | 14 + .../manual_let_else/manual_let_else.stderr | 15 + .../ui-toml/path_ends_with_ext/clippy.toml | 1 + .../path_ends_with_ext/path_ends_with_ext.rs | 9 + .../ui-toml/result_large_err/clippy.toml | 1 + .../result_large_err/result_large_err.rs | 10 + .../result_large_err/result_large_err.stderr | 12 + .../toml_unknown_key/conf_unknown_key.stderr | 2 + .../too_large_for_stack/boxed_local.rs | 5 + .../too_large_for_stack/boxed_local.stderr | 11 + .../ui-toml/too_large_for_stack/clippy.toml | 1 + .../too_large_for_stack/useless_vec.fixed | 9 + .../too_large_for_stack/useless_vec.rs | 9 + .../too_large_for_stack/useless_vec.stderr | 11 + .../ui-toml/too_many_arguments/clippy.toml | 1 + .../too_many_arguments/too_many_arguments.rs | 7 + .../too_many_arguments.stderr | 11 + .../tests/ui-toml/type_complexity/clippy.toml | 1 + .../type_complexity/type_complexity.rs | 7 + .../type_complexity/type_complexity.stderr | 11 + .../type_repetition_in_bounds/clippy.toml | 1 + .../ui-toml/type_repetition_in_bounds/main.rs | 18 + .../type_repetition_in_bounds/main.stderr | 12 + .../undocumented_unsafe_blocks/clippy.toml | 2 - .../default/clippy.toml | 2 + .../disabled/clippy.toml | 3 + ...undocumented_unsafe_blocks.default.stderr} | 74 +- ...ndocumented_unsafe_blocks.disabled.stderr} | 132 +- .../undocumented_unsafe_blocks.rs | 30 +- .../unnecessary_box_returns/clippy.toml | 1 + .../unnecessary_box_returns.fixed | 11 + .../unnecessary_box_returns.rs | 11 + .../unnecessary_box_returns.stderr | 12 + .../ui-toml/verbose_bit_mask/clippy.toml | 1 + .../verbose_bit_mask/verbose_bit_mask.fixed | 7 + .../verbose_bit_mask/verbose_bit_mask.rs | 7 + .../verbose_bit_mask/verbose_bit_mask.stderr | 11 + .../ui-toml/wildcard_imports/clippy.toml | 1 + .../wildcard_imports/wildcard_imports.fixed | 11 + .../wildcard_imports/wildcard_imports.rs | 11 + .../wildcard_imports/wildcard_imports.stderr | 11 + .../tests/ui/auxiliary/proc_macro_derive.rs | 28 + .../clippy/tests/ui/await_holding_lock.stderr | 137 +- .../tests/ui/await_holding_refcell_ref.stderr | 67 +- src/tools/clippy/tests/ui/box_default.fixed | 2 +- src/tools/clippy/tests/ui/box_default.rs | 2 +- src/tools/clippy/tests/ui/cast.rs | 4 + .../tests/ui/cast_lossless_integer.fixed | 11 + .../clippy/tests/ui/cast_lossless_integer.rs | 11 + .../tests/ui/cast_lossless_integer.stderr | 14 +- .../clippy/tests/ui/crashes/ice-10645.stderr | 4 +- .../clippy/tests/ui/crashes/ice-6251.stderr | 2 +- .../clippy/tests/ui/crashes/ice-6252.stderr | 2 +- src/tools/clippy/tests/ui/eta.fixed | 3 +- src/tools/clippy/tests/ui/eta.rs | 3 +- src/tools/clippy/tests/ui/eta.stderr | 54 +- .../ui/extra_unused_type_parameters.fixed | 15 + .../tests/ui/extra_unused_type_parameters.rs | 15 + .../tests/ui/filter_map_bool_then.fixed | 24 + .../clippy/tests/ui/filter_map_bool_then.rs | 24 + .../tests/ui/filter_map_bool_then.stderr | 26 +- src/tools/clippy/tests/ui/functions.stderr | 6 +- src/tools/clippy/tests/ui/future_not_send.rs | 1 + .../clippy/tests/ui/future_not_send.stderr | 71 +- .../tests/ui/ignored_unit_patterns.fixed | 15 + .../clippy/tests/ui/ignored_unit_patterns.rs | 15 + .../tests/ui/ignored_unit_patterns.stderr | 24 +- src/tools/clippy/tests/ui/infinite_loop.rs | 2 - .../clippy/tests/ui/infinite_loop.stderr | 33 +- .../clippy/tests/ui/into_iter_without_iter.rs | 124 + .../tests/ui/into_iter_without_iter.stderr | 114 + .../after_proc_macros.rs | 11 + .../auxiliary/submodule.rs | 4 + .../block_module.stderr | 2 - .../items_after_test_module/in_submodule.rs | 8 + .../in_submodule.stderr | 14 + .../multiple_modules.rs | 11 + .../{block_module.rs => root_module.fixed} | 15 +- .../ui/items_after_test_module/root_module.rs | 22 + .../root_module.stderr | 20 + .../clippy/tests/ui/iter_without_into_iter.rs | 120 + .../tests/ui/iter_without_into_iter.stderr | 150 + .../clippy/tests/ui/len_without_is_empty.rs | 23 + .../tests/ui/len_without_is_empty.stderr | 8 +- .../clippy/tests/ui/let_underscore_future.rs | 2 - .../tests/ui/let_underscore_future.stderr | 17 +- src/tools/clippy/tests/ui/let_unit.fixed | 2 + src/tools/clippy/tests/ui/let_unit.rs | 2 + .../clippy/tests/ui/manual_hash_one.fixed | 89 + src/tools/clippy/tests/ui/manual_hash_one.rs | 89 + .../clippy/tests/ui/manual_hash_one.stderr | 56 + .../tests/ui/manual_let_else_match.fixed | 4 + .../clippy/tests/ui/manual_let_else_match.rs | 8 + .../tests/ui/manual_let_else_match.stderr | 12 +- .../clippy/tests/ui/manual_map_option.fixed | 1 + .../clippy/tests/ui/manual_map_option.rs | 1 + .../clippy/tests/ui/manual_map_option.stderr | 42 +- .../tests/ui/manual_non_exhaustive_enum.rs | 3 +- .../ui/manual_non_exhaustive_enum.stderr | 20 +- .../ui/match_same_arms_non_exhaustive.rs | 20 +- .../ui/match_same_arms_non_exhaustive.stderr | 16 +- .../clippy/tests/ui/must_use_unit.stderr | 4 +- src/tools/clippy/tests/ui/mut_key.rs | 2 - src/tools/clippy/tests/ui/mut_key.stderr | 41 +- src/tools/clippy/tests/ui/mut_reference.rs | 2 - .../clippy/tests/ui/mut_reference.stderr | 17 +- .../clippy/tests/ui/needless_borrow.fixed | 290 -- src/tools/clippy/tests/ui/needless_borrow.rs | 290 -- .../clippy/tests/ui/needless_borrow.stderr | 90 +- .../needless_borrows_for_generic_args.fixed | 287 ++ .../ui/needless_borrows_for_generic_args.rs | 287 ++ .../needless_borrows_for_generic_args.stderr | 77 + .../tests/ui/needless_pass_by_ref_mut.rs | 41 +- .../tests/ui/needless_pass_by_ref_mut.stderr | 68 +- .../clippy/tests/ui/needless_raw_string.fixed | 4 + .../clippy/tests/ui/needless_raw_string.rs | 4 + .../tests/ui/needless_raw_string.stderr | 46 +- .../tests/ui/needless_raw_string_hashes.fixed | 3 + .../tests/ui/needless_raw_string_hashes.rs | 3 + .../ui/needless_raw_string_hashes.stderr | 52 +- src/tools/clippy/tests/ui/no_effect_return.rs | 1 + .../clippy/tests/ui/no_effect_return.stderr | 8 +- .../clippy/tests/ui/option_filter_map.fixed | 2 +- .../clippy/tests/ui/option_filter_map.rs | 2 +- .../clippy/tests/ui/path_ends_with_ext.fixed | 36 + .../clippy/tests/ui/path_ends_with_ext.rs | 36 + .../clippy/tests/ui/path_ends_with_ext.stderr | 17 + src/tools/clippy/tests/ui/print_literal.fixed | 18 +- src/tools/clippy/tests/ui/print_literal.rs | 18 +- .../clippy/tests/ui/print_literal.stderr | 124 +- .../clippy/tests/ui/redundant_allocation.rs | 5 + .../clippy/tests/ui/redundant_as_str.fixed | 24 + src/tools/clippy/tests/ui/redundant_as_str.rs | 24 + .../clippy/tests/ui/redundant_as_str.stderr | 17 + .../tests/ui/redundant_field_names.fixed | 11 +- .../clippy/tests/ui/redundant_field_names.rs | 11 +- .../tests/ui/redundant_field_names.stderr | 2 +- .../clippy/tests/ui/redundant_guards.fixed | 50 + src/tools/clippy/tests/ui/redundant_guards.rs | 50 + .../clippy/tests/ui/redundant_guards.stderr | 116 +- src/tools/clippy/tests/ui/redundant_locals.rs | 37 + .../clippy/tests/ui/redundant_locals.stderr | 139 +- src/tools/clippy/tests/ui/regex.rs | 3 +- src/tools/clippy/tests/ui/regex.stderr | 48 +- .../tests/ui/result_map_unit_fn_unfixable.rs | 2 +- .../ui/should_impl_trait/method_list_2.rs | 2 - .../ui/should_impl_trait/method_list_2.stderr | 36 +- .../tests/ui/slow_vector_initialization.rs | 2 - .../ui/slow_vector_initialization.stderr | 11 +- .../clippy/tests/ui/std_instead_of_core.fixed | 11 + .../clippy/tests/ui/std_instead_of_core.rs | 11 + .../tests/ui/std_instead_of_core.stderr | 22 +- .../clippy/tests/ui/transmute_null_to_fn.rs | 11 + .../tests/ui/transmute_null_to_fn.stderr | 26 +- .../tests/ui/undocumented_unsafe_blocks.rs | 534 --- .../tests/ui/unnecessary_literal_unwrap.fixed | 4 +- .../ui/unnecessary_literal_unwrap.stderr | 4 +- .../ui/unnecessary_map_on_constructor.fixed | 56 + .../ui/unnecessary_map_on_constructor.rs | 56 + .../ui/unnecessary_map_on_constructor.stderr | 53 + .../tests/ui/unnecessary_to_owned.fixed | 2 +- .../clippy/tests/ui/unnecessary_to_owned.rs | 2 +- .../tests/ui/used_underscore_binding.rs | 28 +- .../tests/ui/used_underscore_binding.stderr | 47 +- .../clippy/tests/ui/useless_conversion.fixed | 91 + .../clippy/tests/ui/useless_conversion.rs | 91 + .../clippy/tests/ui/useless_conversion.stderr | 70 +- src/tools/clippy/tests/ui/vec_box_sized.fixed | 5 + src/tools/clippy/tests/ui/vec_box_sized.rs | 5 + .../clippy/tests/ui/wildcard_imports.fixed | 28 + src/tools/clippy/tests/ui/wildcard_imports.rs | 28 + .../clippy/tests/ui/wildcard_imports.stderr | 38 +- .../wildcard_imports_2021.edition2018.fixed | 28 + .../wildcard_imports_2021.edition2018.stderr | 38 +- .../wildcard_imports_2021.edition2021.fixed | 28 + .../wildcard_imports_2021.edition2021.stderr | 38 +- .../clippy/tests/ui/wildcard_imports_2021.rs | 28 + src/tools/clippy/tests/ui/write_literal.fixed | 14 +- src/tools/clippy/tests/ui/write_literal.rs | 14 +- .../clippy/tests/ui/write_literal.stderr | 74 +- src/tools/clippy/tests/ui/write_literal_2.rs | 16 +- .../clippy/tests/ui/write_literal_2.stderr | 82 +- src/tools/compiletest/src/common.rs | 26 + src/tools/compiletest/src/header/needs.rs | 37 +- src/tools/compiletest/src/header/tests.rs | 234 +- src/tools/compiletest/src/util.rs | 102 - src/tools/generate-windows-sys/Cargo.toml | 2 +- src/tools/generate-windows-sys/src/main.rs | 31 +- src/tools/lld-wrapper/src/main.rs | 4 +- src/tools/miri/.github/workflows/ci.yml | 4 +- src/tools/miri/CONTRIBUTING.md | 17 +- src/tools/miri/Cargo.lock | 438 ++- src/tools/miri/Cargo.toml | 4 +- src/tools/miri/README.md | 10 +- .../bench-cargo-miri/invalidate/Cargo.lock | 7 + .../bench-cargo-miri/invalidate/Cargo.toml | 8 + .../bench-cargo-miri/invalidate/src/main.rs | 4 + src/tools/miri/cargo-miri/Cargo.lock | 296 +- src/tools/miri/cargo-miri/Cargo.toml | 4 +- src/tools/miri/cargo-miri/src/phases.rs | 4 +- src/tools/miri/cargo-miri/src/setup.rs | 12 +- src/tools/miri/ci.sh | 2 +- src/tools/miri/miri-script/Cargo.lock | 216 +- src/tools/miri/miri-script/Cargo.toml | 4 +- src/tools/miri/miri-script/src/commands.rs | 9 +- src/tools/miri/rust-version | 2 +- src/tools/miri/src/bin/miri.rs | 19 +- src/tools/miri/src/borrow_tracker/mod.rs | 25 +- .../stacked_borrows/diagnostics.rs | 10 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 61 +- .../tree_borrows/diagnostics.rs | 21 +- .../borrow_tracker/tree_borrows/exhaustive.rs | 111 + .../src/borrow_tracker/tree_borrows/mod.rs | 116 +- .../src/borrow_tracker/tree_borrows/perms.rs | 316 +- .../src/borrow_tracker/tree_borrows/tree.rs | 495 +-- .../borrow_tracker/tree_borrows/tree/tests.rs | 661 ++++ .../src/borrow_tracker/tree_borrows/unimap.rs | 7 +- src/tools/miri/src/concurrency/data_race.rs | 8 +- src/tools/miri/src/concurrency/thread.rs | 3 +- src/tools/miri/src/helpers.rs | 24 +- src/tools/miri/src/helpers/convert.rs | 49 - src/tools/miri/src/lib.rs | 4 +- src/tools/miri/src/machine.rs | 65 +- src/tools/miri/src/operator.rs | 22 +- src/tools/miri/src/shims/backtrace.rs | 5 +- src/tools/miri/src/shims/dlsym.rs | 48 - src/tools/miri/src/shims/foreign_items.rs | 486 +-- src/tools/miri/src/shims/intrinsics/mod.rs | 20 +- src/tools/miri/src/shims/intrinsics/simd.rs | 140 +- src/tools/miri/src/shims/mod.rs | 4 +- .../miri/src/shims/unix/android/dlsym.rs | 54 - .../src/shims/unix/android/foreign_items.rs | 26 +- src/tools/miri/src/shims/unix/android/mod.rs | 1 - src/tools/miri/src/shims/unix/dlsym.rs | 55 - .../miri/src/shims/unix/foreign_items.rs | 53 +- .../miri/src/shims/unix/freebsd/dlsym.rs | 36 - .../src/shims/unix/freebsd/foreign_items.rs | 15 +- src/tools/miri/src/shims/unix/freebsd/mod.rs | 1 - src/tools/miri/src/shims/unix/fs.rs | 35 +- src/tools/miri/src/shims/unix/linux/dlsym.rs | 40 - .../src/shims/unix/linux/foreign_items.rs | 18 +- src/tools/miri/src/shims/unix/linux/mod.rs | 1 - src/tools/miri/src/shims/unix/macos/dlsym.rs | 52 - .../src/shims/unix/macos/foreign_items.rs | 28 +- src/tools/miri/src/shims/unix/macos/mod.rs | 1 - src/tools/miri/src/shims/unix/mod.rs | 1 - src/tools/miri/src/shims/windows/dlsym.rs | 82 - .../miri/src/shims/windows/foreign_items.rs | 103 +- src/tools/miri/src/shims/windows/mod.rs | 1 - src/tools/miri/src/shims/x86/mod.rs | 148 +- src/tools/miri/src/shims/x86/sse.rs | 26 +- src/tools/miri/src/shims/x86/sse2.rs | 153 +- src/tools/miri/src/shims/x86/sse3.rs | 90 + src/tools/miri/src/shims/x86/ssse3.rs | 199 + src/tools/miri/test_dependencies/Cargo.lock | 252 +- src/tools/miri/test_dependencies/Cargo.toml | 2 +- src/tools/miri/tests/compiletest.rs | 109 +- .../libc_pthread_create_main_terminate.rs | 0 .../libc_pthread_create_main_terminate.stderr | 0 .../libc_pthread_create_too_few_args.rs | 0 .../libc_pthread_create_too_few_args.stderr | 0 .../libc_pthread_create_too_many_args.rs | 0 .../libc_pthread_create_too_many_args.stderr | 0 .../concurrency/libc_pthread_join_detached.rs | 0 .../libc_pthread_join_detached.stderr | 0 .../concurrency/libc_pthread_join_joined.rs | 0 .../libc_pthread_join_joined.stderr | 0 .../concurrency/libc_pthread_join_main.rs | 0 .../concurrency/libc_pthread_join_main.stderr | 0 .../concurrency/libc_pthread_join_multiple.rs | 0 .../libc_pthread_join_multiple.stderr | 0 .../concurrency/libc_pthread_join_self.rs | 0 .../concurrency/libc_pthread_join_self.stderr | 0 .../concurrency/unwind_top_of_stack.rs | 0 .../concurrency/unwind_top_of_stack.stderr | 2 + .../shims/fs/close_stdout.rs | 0 .../shims/fs/close_stdout.stderr | 0 .../shims/fs/isolated_stdin.rs | 0 .../shims/fs/isolated_stdin.stderr | 0 .../shims/fs/mkstemp_immutable_arg.rs | 0 .../shims/fs/mkstemp_immutable_arg.stderr | 0 .../shims/fs/read_from_stdout.rs | 0 .../shims/fs/read_from_stdout.stderr | 0 .../fs/unix_open_missing_required_mode.rs | 0 .../fs/unix_open_missing_required_mode.stderr | 0 .../shims/fs/write_to_stdin.rs | 0 .../shims/fs/write_to_stdin.stderr | 0 .../{fail => fail-dep}/shims/memchr_null.rs | 0 .../shims/memchr_null.stderr | 0 .../{fail => fail-dep}/shims/memcmp_null.rs | 0 .../shims/memcmp_null.stderr | 0 .../{fail => fail-dep}/shims/memcmp_zero.rs | 0 .../shims/memcmp_zero.stderr | 0 .../{fail => fail-dep}/shims/memcpy_zero.rs | 0 .../shims/memcpy_zero.stderr | 0 .../{fail => fail-dep}/shims/memrchr_null.rs | 0 .../shims/memrchr_null.stderr | 0 .../shims/mmap_invalid_dealloc.rs | 0 .../shims/mmap_invalid_dealloc.stderr | 0 .../shims/mmap_use_after_munmap.rs | 0 .../shims/mmap_use_after_munmap.stderr | 0 .../tests/{fail => fail-dep}/shims/munmap.rs | 0 .../{fail => fail-dep}/shims/munmap.stderr | 0 .../shims/munmap_partial.rs | 0 .../shims/munmap_partial.stderr | 0 .../sync/libc_pthread_cond_double_destroy.rs | 0 .../libc_pthread_cond_double_destroy.stderr | 0 .../libc_pthread_condattr_double_destroy.rs | 0 ...ibc_pthread_condattr_double_destroy.stderr | 0 .../sync/libc_pthread_mutex_NULL_deadlock.rs | 0 .../libc_pthread_mutex_NULL_deadlock.stderr | 0 .../shims/sync/libc_pthread_mutex_deadlock.rs | 0 .../sync/libc_pthread_mutex_deadlock.stderr | 0 .../libc_pthread_mutex_default_deadlock.rs | 0 ...libc_pthread_mutex_default_deadlock.stderr | 0 .../sync/libc_pthread_mutex_destroy_locked.rs | 0 .../libc_pthread_mutex_destroy_locked.stderr | 0 .../sync/libc_pthread_mutex_double_destroy.rs | 0 .../libc_pthread_mutex_double_destroy.stderr | 0 .../libc_pthread_mutex_normal_deadlock.rs | 0 .../libc_pthread_mutex_normal_deadlock.stderr | 0 ...bc_pthread_mutex_normal_unlock_unlocked.rs | 0 ...thread_mutex_normal_unlock_unlocked.stderr | 0 .../sync/libc_pthread_mutex_wrong_owner.rs | 0 .../libc_pthread_mutex_wrong_owner.stderr | 0 .../libc_pthread_mutexattr_double_destroy.rs | 0 ...bc_pthread_mutexattr_double_destroy.stderr | 0 ...libc_pthread_rwlock_destroy_read_locked.rs | 0 ..._pthread_rwlock_destroy_read_locked.stderr | 0 ...ibc_pthread_rwlock_destroy_write_locked.rs | 0 ...pthread_rwlock_destroy_write_locked.stderr | 0 .../libc_pthread_rwlock_double_destroy.rs | 0 .../libc_pthread_rwlock_double_destroy.stderr | 0 ...wlock_read_write_deadlock_single_thread.rs | 0 ...k_read_write_deadlock_single_thread.stderr | 0 .../libc_pthread_rwlock_read_wrong_owner.rs | 0 ...ibc_pthread_rwlock_read_wrong_owner.stderr | 0 .../libc_pthread_rwlock_unlock_unlocked.rs | 0 ...libc_pthread_rwlock_unlock_unlocked.stderr | 0 ...libc_pthread_rwlock_write_read_deadlock.rs | 0 ..._pthread_rwlock_write_read_deadlock.stderr | 0 ...wlock_write_read_deadlock_single_thread.rs | 0 ...k_write_read_deadlock_single_thread.stderr | 0 ...ibc_pthread_rwlock_write_write_deadlock.rs | 0 ...pthread_rwlock_write_write_deadlock.stderr | 0 ...lock_write_write_deadlock_single_thread.rs | 0 ..._write_write_deadlock_single_thread.stderr | 0 .../libc_pthread_rwlock_write_wrong_owner.rs | 0 ...bc_pthread_rwlock_write_wrong_owner.stderr | 0 .../tests/{fail => fail-dep}/tokio/sleep.rs | 0 .../{fail => fail-dep}/tokio/sleep.stderr | 0 .../unsupported_incomplete_function.rs | 0 .../unsupported_incomplete_function.stderr | 0 .../both_borrows/aliasing_mut1.tree.stderr | 6 +- .../both_borrows/aliasing_mut2.tree.stderr | 6 +- .../both_borrows/aliasing_mut3.tree.stderr | 6 +- .../newtype_pair_retagging.stack.stderr | 2 +- .../newtype_pair_retagging.tree.stderr | 8 +- .../newtype_retagging.stack.stderr | 2 +- .../newtype_retagging.tree.stderr | 8 +- .../retag_data_race_protected_read.rs | 29 - ...retag_data_race_protected_read.tree.stderr | 25 - .../arg_inplace_mutate.tree.stderr | 8 +- .../arg_inplace_observe_during.tree.stderr | 8 +- .../exported_symbol_bad_unwind1.stderr | 2 + .../exported_symbol_bad_unwind2.both.stderr | 2 +- ...orted_symbol_bad_unwind2.definition.stderr | 2 +- .../return_pointer_aliasing.tree.stderr | 8 +- .../return_pointer_aliasing2.stderr | 8 +- .../simd_feature_flag_difference.rs | 30 + .../simd_feature_flag_difference.stderr | 20 + .../tests/fail/generator-pinned-moved.stderr | 4 +- .../intrinsics/uninit_uninhabited_type.stderr | 2 +- .../tests/fail/intrinsics/zero_fn_ptr.stderr | 2 +- .../fail/panic/bad_miri_start_panic.stderr | 2 + .../miri/tests/fail/panic/bad_unwind.stderr | 6 +- .../miri/tests/fail/panic/double_panic.stderr | 2 +- .../miri/tests/fail/panic/panic_abort1.stderr | 2 +- .../miri/tests/fail/panic/panic_abort2.stderr | 2 +- .../miri/tests/fail/panic/panic_abort3.stderr | 2 +- .../miri/tests/fail/panic/panic_abort4.stderr | 2 +- .../tests/fail/shims/fs/isolated_file.stderr | 6 +- .../deallocate_against_protector1.stderr | 2 +- .../retag_data_race_protected_read.rs | 30 + .../retag_data_race_protected_read.stderr} | 0 .../tests/fail/terminate-terminator.stderr | 2 +- .../reserved/cell-protected-write.stderr | 18 +- .../reserved/int-protected-write.stderr | 14 +- .../tests/fail/tree_borrows/spurious_read.rs | 117 + .../fail/tree_borrows/spurious_read.stderr | 44 + .../tree_borrows/strongly-protected.stderr | 2 +- .../tests/fail/unwind-action-terminate.stderr | 2 +- .../miri/tests/pass-dep/shims/libc-misc.rs | 14 + .../tests/pass/backtrace/backtrace-api-v0.rs | 2 + .../pass/backtrace/backtrace-api-v0.stderr | 15 +- .../pass/backtrace/backtrace-api-v0.stdout | 2 +- .../tests/pass/backtrace/backtrace-api-v1.rs | 2 + .../pass/backtrace/backtrace-api-v1.stderr | 15 +- .../pass/backtrace/backtrace-api-v1.stdout | 2 +- src/tools/miri/tests/pass/float.rs | 10 + .../function_calls/disable_abi_check.stderr | 2 + .../miri/tests/pass/function_pointers.rs | 20 +- src/tools/miri/tests/pass/intrinsics-math.rs | 27 +- .../miri/tests/pass/intrinsics-x86-avx512.rs | 217 ++ .../miri/tests/pass/intrinsics-x86-sse.rs | 2019 +++++----- .../miri/tests/pass/intrinsics-x86-sse2.rs | 1513 ++++---- .../tests/pass/intrinsics-x86-sse3-ssse3.rs | 395 ++ src/tools/miri/tests/pass/intrinsics-x86.rs | 79 +- src/tools/miri/tests/pass/portable-simd.rs | 15 +- .../tree_borrows/cell-alternate-writes.stderr | 12 +- .../pass/tree_borrows/end-of-protector.stderr | 48 +- .../tests/pass/tree_borrows/formatting.stderr | 50 +- .../pass/tree_borrows/read_retag_no_race.rs | 114 + .../tree_borrows/read_retag_no_race.stderr | 8 + .../pass/tree_borrows/reborrow-is-read.stderr | 18 +- .../tests/pass/tree_borrows/reserved.stderr | 68 +- .../tests/pass/tree_borrows/spurious_read.rs | 115 + .../pass/tree_borrows/spurious_read.stderr | 16 + .../tests/pass/tree_borrows/tree-borrows.rs | 19 + .../pass/tree_borrows/unique.default.stderr | 24 +- .../pass/tree_borrows/unique.uniq.stderr | 30 +- .../tree_borrows/vec_unique.default.stderr | 6 +- .../pass/tree_borrows/vec_unique.uniq.stderr | 10 +- src/tools/miri/triagebot.toml | 5 +- src/tools/opt-dist/Cargo.toml | 1 + src/tools/opt-dist/src/main.rs | 9 +- src/tools/opt-dist/src/tests.rs | 2 +- src/tools/opt-dist/src/utils/artifact_size.rs | 61 + src/tools/opt-dist/src/utils/mod.rs | 51 +- src/tools/rustfmt/src/items.rs | 3 +- src/tools/tidy/src/deps.rs | 10 +- src/tools/tidy/src/pal.rs | 1 + src/version | 2 +- .../closure-inherit-target-feature.rs | 58 + .../stack-protector-heuristics-effect.rs | 3 +- tests/codegen/async-fn-debug-awaitee-field.rs | 10 +- tests/codegen/debug-fndef-size.rs | 18 + tests/codegen/issue-97217.rs | 22 + .../issues/issue-105386-ub-in-debuginfo.rs | 4 +- .../macos/i686-macosx-deployment-target.rs | 4 +- .../macos/i686-no-macosx-deployment-target.rs | 2 +- .../macos/x86_64-macosx-deployment-target.rs | 4 +- .../x86_64-no-macosx-deployment-target.rs | 2 +- .../address-sanitizer-globals-tracking.rs | 5 +- .../codegen/sanitizer/memory-track-origins.rs | 11 +- .../codegen/sanitizer/no-sanitize-inlining.rs | 5 +- tests/codegen/sanitizer/no-sanitize.rs | 2 +- tests/codegen/sanitizer/sanitizer-recover.rs | 1 + tests/codegen/simd/simd-wide-sum.rs | 26 +- tests/codegen/unwind-landingpad-cold.rs | 16 + tests/codegen/unwind-landingpad-inline.rs | 39 + .../codegen/vecdeque-nonempty-get-no-panic.rs | 17 + tests/coverage-map/status-quo/async.cov-map | 90 +- tests/coverage-map/status-quo/async2.cov-map | 28 +- tests/coverage-map/status-quo/closure.cov-map | 185 +- .../status-quo/closure_bug.cov-map | 125 +- .../status-quo/closure_macro.cov-map | 22 +- .../status-quo/closure_macro_async.cov-map | 22 +- .../status-quo/conditions.cov-map | 338 +- .../coverage-map/status-quo/continue.cov-map | 74 +- .../coverage-map/status-quo/dead_code.cov-map | 8 +- .../coverage-map/status-quo/generator.cov-map | 39 +- .../status-quo/inline-dead.cov-map | 12 +- tests/coverage-map/status-quo/inline.cov-map | 26 +- .../status-quo/issue-93054.cov-map | 8 +- .../status-quo/lazy_boolean.cov-map | 372 +- .../status-quo/loops_branches.cov-map | 266 +- .../status-quo/no_cov_crate.cov-map | 4 +- .../status-quo/partial_eq.cov-map | 12 +- .../status-quo/simple_loop.cov-map | 23 +- .../status-quo/simple_match.cov-map | 31 +- .../status-quo/test_harness.cov-map | 4 +- .../status-quo/try_error_result.cov-map | 166 +- tests/coverage-map/status-quo/unused.cov-map | 16 +- tests/coverage-map/status-quo/yield.cov-map | 62 +- tests/coverage-map/unreachable.cov-map | 24 + tests/coverage-map/unreachable.rs | 37 + tests/incremental/change_crate_dep_kind.rs | 1 + tests/incremental/hashes/for_loops.rs | 6 +- .../incremental/hashes/function_interfaces.rs | 2 +- tests/incremental/hashes/loop_expressions.rs | 4 +- tests/incremental/hashes/while_loops.rs | 10 +- ...await.a-{closure#0}.generator_resume.0.mir | 22 +- ...await.b-{closure#0}.generator_resume.0.mir | 112 +- ...t_overflow.main.ConstProp.panic-abort.diff | 2 + ..._overflow.main.ConstProp.panic-unwind.diff | 2 + ...lice.main.ConstProp.32bit.panic-abort.diff | 119 + ...ice.main.ConstProp.32bit.panic-unwind.diff | 123 + ...lice.main.ConstProp.64bit.panic-abort.diff | 119 + ...ice.main.ConstProp.64bit.panic-unwind.diff | 123 + ...n.DataflowConstProp.32bit.panic-abort.diff | 111 + ....DataflowConstProp.32bit.panic-unwind.diff | 115 + ...n.DataflowConstProp.64bit.panic-abort.diff | 111 + ....DataflowConstProp.64bit.panic-unwind.diff | 115 + .../default_boxed_slice.rs | 17 + ...ow.main.DataflowConstProp.panic-abort.diff | 2 + ...w.main.DataflowConstProp.panic-unwind.diff | 2 + .../cycle.cycle.DeadStoreElimination.diff | 29 + ...ycle.DeadStoreElimination.panic-abort.diff | 73 - ...cle.DeadStoreElimination.panic-unwind.diff | 73 - tests/mir-opt/dead-store-elimination/cycle.rs | 37 +- ...stinationPropagation.after.panic-abort.mir | 7 +- ...tinationPropagation.after.panic-unwind.mir | 7 +- ...in.DestinationPropagation.panic-abort.diff | 2 + ...n.DestinationPropagation.panic-unwind.diff | 2 + ...losure#0}.generator_drop.0.panic-abort.mir | 2 +- ...osure#0}.generator_drop.0.panic-unwind.mir | 2 +- ...e#0}.StateTransform.before.panic-abort.mir | 2 +- ...#0}.StateTransform.before.panic-unwind.mir | 2 +- ...ny.main-{closure#0}.generator_resume.0.mir | 10 +- .../gvn.arithmetic.GVN.panic-abort.diff | 342 ++ .../gvn.arithmetic.GVN.panic-unwind.diff | 342 ++ ...vn.arithmetic_checked.GVN.panic-abort.diff | 389 ++ ...n.arithmetic_checked.GVN.panic-unwind.diff | 389 ++ .../gvn.arithmetic_float.GVN.panic-abort.diff | 165 + ...gvn.arithmetic_float.GVN.panic-unwind.diff | 165 + tests/mir-opt/gvn.cast.GVN.panic-abort.diff | 501 +++ tests/mir-opt/gvn.cast.GVN.panic-unwind.diff | 501 +++ .../gvn.dereferences.GVN.panic-abort.diff | 191 + .../gvn.dereferences.GVN.panic-unwind.diff | 191 + ...gvn.multiple_branches.GVN.panic-abort.diff | 198 + ...vn.multiple_branches.GVN.panic-unwind.diff | 198 + .../gvn.references.GVN.panic-abort.diff | 105 + .../gvn.references.GVN.panic-unwind.diff | 113 + .../gvn.repeated_index.GVN.panic-abort.diff | 76 + .../gvn.repeated_index.GVN.panic-unwind.diff | 76 + tests/mir-opt/gvn.rs | 253 ++ tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 275 ++ .../mir-opt/gvn.slices.GVN.panic-unwind.diff | 275 ++ ...xpression_elimination.GVN.panic-abort.diff | 883 +++++ ...pression_elimination.GVN.panic-unwind.diff | 883 +++++ .../gvn.wrap_unwrap.GVN.panic-abort.diff | 45 + .../gvn.wrap_unwrap.GVN.panic-unwind.diff | 45 + .../inline_closure.foo.Inline.after.mir | 6 +- ...e_closure_borrows_arg.foo.Inline.after.mir | 6 +- ...line_closure_captures.foo.Inline.after.mir | 14 +- ...ine_generator.main.Inline.panic-abort.diff | 101 +- ...ne_generator.main.Inline.panic-unwind.diff | 74 +- ...nto_box_place.main.Inline.panic-abort.diff | 10 + ...to_box_place.main.Inline.panic-unwind.diff | 10 + ...issue_106141.outer.Inline.panic-abort.diff | 2 + ...ssue_106141.outer.Inline.panic-unwind.diff | 2 + ...67_inline_as_ref_as_mut.b.Inline.after.mir | 4 + ...67_inline_as_ref_as_mut.d.Inline.after.mir | 4 + ...ine_scopes_parenting.main.Inline.after.mir | 6 +- ...issue_78442.bar.RevealAll.panic-abort.diff | 26 +- ...ssue_78442.bar.RevealAll.panic-unwind.diff | 24 +- ...d.unwrap_unchecked.Inline.panic-abort.diff | 2 + ....unwrap_unchecked.Inline.panic-unwind.diff | 2 + ...unchecked.PreCodegen.after.panic-abort.mir | 2 + ...nchecked.PreCodegen.after.panic-unwind.mir | 2 + ...ument_coverage.bar.InstrumentCoverage.diff | 2 +- ...ment_coverage.main.InstrumentCoverage.diff | 9 +- ...ue_101973.inner.ConstProp.panic-abort.diff | 1 + ...e_101973.inner.ConstProp.panic-unwind.diff | 1 + ..._to_digit.PreCodegen.after.panic-abort.mir | 42 +- ...to_digit.PreCodegen.after.panic-unwind.mir | 42 +- ...cked_ops.step_forward.PreCodegen.after.mir | 43 +- .../loops.filter_mapped.PreCodegen.after.mir | 43 +- .../loops.int_range.PreCodegen.after.mir | 99 +- ...ward_loop.PreCodegen.after.panic-abort.mir | 115 +- ...ard_loop.PreCodegen.after.panic-unwind.mir | 115 +- ...iter_next.PreCodegen.after.panic-abort.mir | 64 +- ...ter_next.PreCodegen.after.panic-unwind.mir | 64 +- ...mple_option_map.ezmap.PreCodegen.after.mir | 6 +- ...variant_a-{closure#0}.PreCodegen.after.mir | 252 +- ...variant_b-{closure#0}.PreCodegen.after.mir | 2 +- ...mut_range.PreCodegen.after.panic-abort.mir | 14 +- ...ut_range.PreCodegen.after.panic-unwind.mir | 14 +- ...ange_loop.PreCodegen.after.panic-abort.mir | 131 +- ...nge_loop.PreCodegen.after.panic-unwind.mir | 131 +- ...erse_loop.PreCodegen.after.panic-abort.mir | 49 +- ...rse_loop.PreCodegen.after.panic-unwind.mir | 49 +- ...ans.outer.PreCodegen.after.panic-abort.mir | 4 +- ...ns.outer.PreCodegen.after.panic-unwind.mir | 4 +- ...yCfg-elaborate-drops.after.panic-abort.mir | 2 +- ...Cfg-elaborate-drops.after.panic-unwind.mir | 2 +- ...yCfg-elaborate-drops.after.panic-abort.mir | 4 +- ...Cfg-elaborate-drops.after.panic-unwind.mir | 4 +- ...t_switch.identity.SeparateConstSwitch.diff | 2 + tests/mir-opt/ssa_unreachable_116212.rs | 14 + tests/run-coverage/unreachable.coverage | 38 + tests/run-coverage/unreachable.rs | 37 + .../obtain-borrowck/driver.rs | 4 +- tests/run-make/const_fn_mir/Makefile | 7 +- .../run-make/incr-foreign-head-span/Makefile | 2 +- tests/run-make/issue-71519/Makefile | 8 - tests/run-make/issue-71519/main.rs | 4 - .../output-default.stdout | 3 - .../run-make/macos-deployment-target/Makefile | 4 +- tests/run-make/metadata-dep-info/Makefile | 6 - tests/run-make/overwrite-input/Makefile | 10 +- .../raw-dylib-alt-calling-convention/Makefile | 12 +- .../raw-dylib-import-name-type/Makefile | 7 +- .../raw-dylib-inline-cross-dylib/Makefile | 7 +- .../run-make/raw-dylib-link-ordinal/Makefile | 7 +- .../raw-dylib-stdcall-ordinal/Makefile | 7 +- .../Makefile | 4 +- .../rust_dep.rs | 2 - tests/run-make/silly-file-names/Makefile | 12 + .../silly-file-names/silly-file-names.rs | 4 + .../silly-file-names.run.stdout | 2 + tests/run-make/tools.mk | 22 + tests/run-make/unknown-mod-stdin/Makefile | 11 +- tests/rustdoc-gui/default-settings.goml | 2 +- tests/rustdoc-js/impl-trait.js | 19 +- tests/rustdoc-js/impl-trait.rs | 6 + ...ustom_code_classes_in_docs-warning3.stderr | 2 + .../broken-link-in-unused-doc-string.stderr | 1 + tests/rustdoc-ui/issue-102467.rs | 15 + tests/rustdoc-ui/issue-102467.stderr | 9 + tests/rustdoc-ui/issues/issue-105742.stderr | 16 + ...-gate-rustdoc_missing_doc_code_examples.rs | 7 +- ...e-rustdoc_missing_doc_code_examples.stderr | 26 +- tests/rustdoc-ui/unescaped_backticks.stderr | 3 + ... anchor-id-duplicate-method-name-25001.rs} | 3 + ...169.rs => anchor-id-trait-method-15169.rs} | 4 + ...8.rs => anchor-id-trait-tymethod-28478.rs} | 3 + ...-20646.rs => assoc-type-bindings-20646.rs} | 2 + tests/rustdoc/auxiliary/enum-variant.rs | 24 + ... => deduplicate-glob-import-impl-21474.rs} | 3 + ...025.rs => deduplicate-trait-impl-22025.rs} | 3 + ...rs => deref-methods-19190-foreign-type.rs} | 4 + ...190-3.rs => deref-methods-19190-inline.rs} | 3 + ...{issue-19190.rs => deref-methods-19190.rs} | 3 + ...ue-13698.rs => doc-hidden-method-13698.rs} | 3 + ...{issue-18199.rs => doc-test-attr-18199.rs} | 1 + .../rustdoc/doctest-hide-empty-line-23106.rs | 10 + ...=> doctest-markdown-inline-parse-23744.rs} | 3 + ...octest-multi-line-string-literal-25944.rs} | 3 + ...5347.rs => document-hidden-items-15347.rs} | 3 + tests/rustdoc/enum-variant-value.rs | 117 + .../{issue-22038.rs => extern-fn-22038.rs} | 3 + ...834.rs => highlight-invalid-rust-12834.rs} | 2 + ...27.rs => ice-reexport-crate-root-28927.rs} | 3 + ...issue-19181.rs => ice-type-error-19181.rs} | 1 + ...ssue-21092.rs => impl-assoc-type-21092.rs} | 3 + .../{issue-20175.rs => impl-ref-20175.rs} | 4 + ...5-1.rs => infinite-redirection-16265-1.rs} | 3 + ...5-2.rs => infinite-redirection-16265-2.rs} | 3 + ...rs => inline-assoc-type-20727-bindings.rs} | 3 + ...> inline-assoc-type-20727-bounds-deref.rs} | 3 + ...> inline-assoc-type-20727-bounds-index.rs} | 3 + ...7.rs => inline-assoc-type-20727-bounds.rs} | 3 + tests/rustdoc/inline_cross/async-fn.rs | 19 + .../inline_cross/auxiliary/async-fn.rs | 18 + .../rustdoc/inline_cross/auxiliary/fn-type.rs | 1 + .../inline_cross/auxiliary/impl_trait_aux.rs | 8 +- .../auxiliary/issue-21801.rs | 0 .../auxiliary/issue-23207-1.rs | 0 .../auxiliary/issue-23207-2.rs | 0 .../auxiliary/issue-27362-aux.rs | 0 .../auxiliary/non_lifetime_binders.rs | 10 + .../const-fn-27362.rs} | 3 + .../deduplicate-inlined-items-23207.rs} | 3 + tests/rustdoc/inline_cross/fn-type.rs | 12 + tests/rustdoc/inline_cross/impl_trait.rs | 10 +- .../inline_cross/non_lifetime_binders.rs | 13 + .../sugar-closure-crate-21801.rs} | 3 + tests/rustdoc/issue-23106.rs | 7 - ...ue-23812.rs => macro-doc-comment-23812.rs} | 3 + .../{issue-16019.rs => macro-ice-16019.rs} | 2 + ...rs => markdown-table-escape-pipe-27862.rs} | 3 + ...> method-link-foreign-trait-impl-17476.rs} | 3 + tests/rustdoc/no-crate-filter.rs | 6 - ...s => primitive-raw-pointer-dox-15318-3.rs} | 2 + ...rs => primitive-raw-pointer-link-15318.rs} | 2 + ...ve-raw-pointer-link-no-inlined-15318-2.rs} | 3 + tests/rustdoc/rfc-2632-const-trait-impl.rs | 22 +- ...-index-primitive-inherent-method-23511.rs} | 3 + ...06.rs => src-link-external-macro-26606.rs} | 5 +- ...6995.rs => src-mod-path-absolute-26995.rs} | 3 + ...9.rs => staged-api-feature-issue-27759.rs} | 3 + ...04.rs => strip-priv-imports-pass-27104.rs} | 3 + .../lint_pass_impl_without_macro.rs | 2 +- .../internal-lints/ty_tykind_usage.rs | 1 - .../internal-lints/ty_tykind_usage.stderr | 32 +- tests/ui-fulldeps/lint-pass-macros.rs | 2 +- .../auxiliary/lint-group-plugin-test.rs | 3 +- .../plugin/auxiliary/lint-plugin-test.rs | 6 +- .../plugin/auxiliary/lint-tool-test.rs | 6 +- .../plugin/lint-plugin-forbid-attrs.stderr | 2 + .../plugin/lint-plugin-forbid-cmdline.stderr | 1 + .../plugin/lint-tool-cmdline-allow.stderr | 2 + .../ui-fulldeps/plugin/lint-tool-test.stderr | 12 + .../diagnostic-derive-doc-comment-field.rs | 2 +- ...diagnostic-derive-doc-comment-field.stderr | 2 +- .../diagnostic-derive.stderr | 2 + .../stable-mir/compilation-result.rs | 3 +- tests/ui-fulldeps/stable-mir/crate-info.rs | 74 +- tests/ui/abi/compatibility.rs | 183 +- tests/ui/abi/relocation_model_pic.rs | 3 +- tests/ui/allocator/not-an-allocator.stderr | 3 + tests/ui/array-slice-vec/vector-no-ann.stderr | 2 +- tests/ui/asm/aarch64/type-check-2.stderr | 2 +- tests/ui/asm/x86_64/issue-96797.rs | 9 +- tests/ui/asm/x86_64/type-check-2.stderr | 2 +- .../defaults-not-assumed-fail.stderr | 1 + .../ui/associated-consts/issue-105330.stderr | 2 +- .../issue-109789.stderr | 1 + .../issue-111879-1.stderr | 4 +- .../regionck-1.stderr | 11 +- .../type-alias-bounds-are-enforced.rs | 8 +- .../type-alias-bounds-are-enforced.stderr | 55 - .../associated-type-bounds/duplicate.stderr | 12 + .../issue-71443-1.stderr | 2 +- .../associated-types-coherence-failure.stderr | 8 +- .../defaults-specialization.stderr | 4 +- .../hr-associated-type-bound-2.stderr | 6 +- .../hr-associated-type-bound-param-2.stderr | 1 + .../associated-types/impl-wf-cycle-1.stderr | 8 +- .../associated-types/impl-wf-cycle-2.stderr | 7 +- .../async-await-let-else.drop-tracking.stderr | 106 - .../async-await-let-else.drop_tracking.stderr | 106 - ...ync-await-let-else.no-drop-tracking.stderr | 90 - ...ync-await-let-else.no_drop_tracking.stderr | 90 - tests/ui/async-await/async-await-let-else.rs | 3 - ...mir.stderr => async-await-let-else.stderr} | 28 +- ...block-control-flow-static-semantics.stderr | 8 +- .../async-error-span.drop_tracking.stderr | 25 - .../async-error-span.no_drop_tracking.stderr | 25 - tests/ui/async-await/async-error-span.rs | 7 +- ...ing_mir.stderr => async-error-span.stderr} | 4 +- .../async-fn-nonsend.drop_tracking.stderr | 49 - .../async-fn-nonsend.no_drop_tracking.stderr | 120 - tests/ui/async-await/async-fn-nonsend.rs | 6 - ...ing_mir.stderr => async-fn-nonsend.stderr} | 12 +- .../ui/async-await/async-is-unwindsafe.stderr | 16 +- tests/ui/async-await/await-sequence.rs | 1 - .../ui/async-await/awaiting-unsized-param.rs | 13 + .../async-await/awaiting-unsized-param.stderr | 21 + .../ui/async-await/const-async-fn-in-main.rs | 7 + .../async-await/const-async-fn-in-main.stderr | 11 + tests/ui/async-await/default-struct-update.rs | 3 - tests/ui/async-await/drop-and-assign.rs | 3 - .../drop-track-bad-field-in-fru.rs | 1 - .../drop-track-bad-field-in-fru.stderr | 4 +- ...-field-assign-nonsend.drop_tracking.stderr | 25 - ...eld-assign-nonsend.no_drop_tracking.stderr | 25 - .../drop-track-field-assign-nonsend.rs | 3 - ...=> drop-track-field-assign-nonsend.stderr} | 6 +- .../ui/async-await/drop-track-field-assign.rs | 3 - ...drop-tracking-unresolved-typeck-results.rs | 3 - ...-tracking-unresolved-typeck-results.stderr | 41 +- .../async-await/feature-self-return-type.rs | 1 - .../feature-self-return-type.stderr | 2 +- .../field-assign-nonsend.drop_tracking.stderr | 25 - ...eld-assign-nonsend.no_drop_tracking.stderr | 25 - tests/ui/async-await/field-assign-nonsend.rs | 3 - ...mir.stderr => field-assign-nonsend.stderr} | 6 +- tests/ui/async-await/field-assign.rs | 3 - .../future-sizes/async-awaiting-fut.stdout | 38 +- .../async-await/future-sizes/large-arg.stdout | 44 +- tests/ui/async-await/generator-desc.stderr | 8 +- .../async-await/generator-not-future.stderr | 12 +- .../in-trait/async-associated-types.rs | 3 +- .../in-trait/async-default-fn-overridden.rs | 2 + ...nc-example-desugared-boxed-in-trait.stderr | 4 +- .../in-trait/async-example-desugared-extra.rs | 1 + .../in-trait/async-example-desugared.rs | 1 + .../ui/async-await/in-trait/async-example.rs | 3 + .../in-trait/async-generics-and-bounds.stderr | 38 +- .../in-trait/async-generics.stderr | 38 +- .../in-trait/async-lifetimes-and-bounds.rs | 1 + .../async-await/in-trait/async-lifetimes.rs | 1 + .../in-trait/async-recursive-generic.stderr | 4 +- .../in-trait/async-recursive.stderr | 4 +- .../in-trait/auxiliary/foreign-async-fn.rs | 7 + ...project-to-specializable-projection.stderr | 8 +- .../ui/async-await/in-trait/early-bound-1.rs | 1 + .../ui/async-await/in-trait/early-bound-2.rs | 1 + .../async-await/in-trait/fn-not-async-err2.rs | 2 +- .../in-trait/fn-not-async-err2.stderr | 2 +- .../ui/async-await/in-trait/implied-bounds.rs | 2 + .../indirect-recursion-issue-112047.rs | 2 +- .../indirect-recursion-issue-112047.stderr | 9 +- tests/ui/async-await/in-trait/issue-102138.rs | 2 + tests/ui/async-await/in-trait/issue-102219.rs | 1 + tests/ui/async-await/in-trait/issue-102310.rs | 1 + tests/ui/async-await/in-trait/issue-104678.rs | 1 + .../in-trait/missing-feature-flag.stderr | 12 +- .../in-trait/missing-send-bound.stderr | 5 + tests/ui/async-await/in-trait/nested-rpit.rs | 1 + .../normalize-opaque-with-bound-vars.rs | 1 + .../in-trait/send-on-async-fn-in-trait.fixed | 20 + .../in-trait/send-on-async-fn-in-trait.rs | 20 + .../in-trait/send-on-async-fn-in-trait.stderr | 43 + .../send-on-foreign-async-fn-in-trait.rs | 15 + .../send-on-foreign-async-fn-in-trait.stderr | 23 + tests/ui/async-await/in-trait/warn.rs | 23 + tests/ui/async-await/in-trait/warn.stderr | 20 + tests/ui/async-await/issue-108572.fixed | 16 + tests/ui/async-await/issue-108572.rs | 7 +- tests/ui/async-await/issue-108572.stderr | 9 +- .../issue-61949-self-return-type.rs | 28 - .../issue-61949-self-return-type.stderr | 26 - .../issue-64130-1-sync.drop_tracking.stderr | 25 - ...issue-64130-1-sync.no_drop_tracking.stderr | 25 - tests/ui/async-await/issue-64130-1-sync.rs | 3 - ...g_mir.stderr => issue-64130-1-sync.stderr} | 6 +- .../issue-64130-2-send.drop_tracking.stderr | 28 - ...issue-64130-2-send.no_drop_tracking.stderr | 28 - tests/ui/async-await/issue-64130-2-send.rs | 6 +- ...g_mir.stderr => issue-64130-2-send.stderr} | 16 +- .../issue-64130-3-other.drop_tracking.stderr | 27 - ...ssue-64130-3-other.no_drop_tracking.stderr | 27 - tests/ui/async-await/issue-64130-3-other.rs | 6 +- ..._mir.stderr => issue-64130-3-other.stderr} | 12 +- ...ue-64130-4-async-move.drop-tracking.stderr | 26 - ...64130-4-async-move.no_drop_tracking.stderr | 26 - .../async-await/issue-64130-4-async-move.rs | 7 +- .../issue-64130-non-send-future-diags.stderr | 2 - ...-67252-unnamed-future.drop_tracking.stderr | 30 - ...252-unnamed-future.no_drop_tracking.stderr | 30 - .../async-await/issue-67252-unnamed-future.rs | 5 +- ...derr => issue-67252-unnamed-future.stderr} | 8 +- .../issue-68112.drop_tracking.stderr | 82 - .../issue-68112.no_drop_tracking.stderr | 82 - tests/ui/async-await/issue-68112.rs | 3 - ...tracking_mir.stderr => issue-68112.stderr} | 22 +- tests/ui/async-await/issue-68523-start.rs | 2 +- tests/ui/async-await/issue-68523-start.stderr | 4 +- .../issue-70818.drop_tracking.stderr | 18 - .../issue-70818.no_drop_tracking.stderr | 18 - tests/ui/async-await/issue-70818.rs | 3 - ...tracking_mir.stderr => issue-70818.stderr} | 4 +- ...e-70935-complex-spans.drop_tracking.stderr | 41 - ...0935-complex-spans.no_drop_tracking.stderr | 21 - .../async-await/issue-70935-complex-spans.rs | 6 +- ...tderr => issue-70935-complex-spans.stderr} | 10 +- tests/ui/async-await/issue-71137.stderr | 3 - tests/ui/async-await/issue-73137.rs | 3 - ...ype-err-drop-tracking.drop_tracking.stderr | 11 - ...err-drop-tracking.drop_tracking_mir.stderr | 11 - ...-err-drop-tracking.no_drop_tracking.stderr | 11 - .../issue-73741-type-err-drop-tracking.rs | 17 - .../issue-86507.drop_tracking_mir.stderr | 23 - .../issue-86507.no_drop_tracking.stderr | 23 - tests/ui/async-await/issue-86507.rs | 3 - ...rop_tracking.stderr => issue-86507.stderr} | 6 +- tests/ui/async-await/issue-93197.rs | 1 - tests/ui/async-await/issue-93648.rs | 3 - .../issues/auxiliary/issue_67893.rs | 7 +- tests/ui/async-await/issues/issue-107280.rs | 5 - .../ui/async-await/issues/issue-107280.stderr | 67 +- .../async-await/issues/issue-62009-1.stderr | 10 +- ...6-raw-ptr-not-send.no_drop_tracking.stderr | 32 - .../issues/issue-65436-raw-ptr-not-send.rs | 7 +- .../issues/issue-67611-static-mut-refs.rs | 4 - tests/ui/async-await/issues/issue-67893.rs | 2 +- .../ui/async-await/issues/issue-67893.stderr | 28 +- tests/ui/async-await/issues/issue-78600.rs | 2 +- .../ui/async-await/issues/issue-78600.stderr | 14 - .../async-await/large_moves.attribute.stderr | 39 - .../ui/async-await/large_moves.option.stderr | 39 - ...async-impl-trait-type.drop_tracking.stderr | 21 - ...nc-impl-trait-type.no_drop_tracking.stderr | 21 - ...utually-recursive-async-impl-trait-type.rs | 4 - ...ly-recursive-async-impl-trait-type.stderr} | 8 +- tests/ui/async-await/non-trivial-drop.rs | 3 - ...rop-partial-reinit.no_drop_tracking.stderr | 35 - .../partial-drop-partial-reinit.rs | 3 - ...err => partial-drop-partial-reinit.stderr} | 10 +- .../ui/async-await/pin-needed-to-poll.stderr | 8 +- ...async-impl-trait-type.drop_tracking.stderr | 12 - ...nc-impl-trait-type.no_drop_tracking.stderr | 12 - .../recursive-async-impl-trait-type.rs | 3 - ...=> recursive-async-impl-trait-type.stderr} | 4 +- .../issue-110963-early.current.stderr | 25 +- .../issue-110963-early.next.stderr | 25 +- .../issue-110963-early.stderr | 26 +- ...unresolved_type_param.drop_tracking.stderr | 39 - ...esolved_type_param.no_drop_tracking.stderr | 63 - tests/ui/async-await/unresolved_type_param.rs | 26 +- ...ir.stderr => unresolved_type_param.stderr} | 2 +- tests/ui/async-await/unsized-across-await.rs | 16 + .../async-await/unsized-across-await.stderr | 21 + tests/ui/auto-traits/pre-cfg.rs | 8 + tests/ui/auto-traits/pre-cfg.stderr | 13 + .../block-must-not-have-result-res.stderr | 2 +- tests/ui/block-result/issue-20862.stderr | 4 +- tests/ui/block-result/issue-22645.stderr | 2 +- tests/ui/block-result/issue-5500.stderr | 2 +- .../ui/borrowck/async-reference-generality.rs | 3 +- .../async-reference-generality.stderr | 27 - .../erase-error-in-mir-drop-tracking.rs | 23 - .../erase-error-in-mir-drop-tracking.stderr | 24 - ...ted-closure-outlives-borrowed-value.stderr | 2 +- tests/ui/borrowck/issue-81899.stderr | 2 +- .../issue-88434-minimal-example.stderr | 2 +- ...-88434-removal-index-should-be-less.stderr | 2 +- tests/ui/borrowck/issue-92157.rs | 2 +- tests/ui/borrowck/issue-92157.stderr | 9 +- ...5079-missing-move-in-nested-closure.stderr | 2 +- ...regions-bound-missing-bound-in-impl.stderr | 1 + .../builtin-superkinds-self-type.stderr | 7 +- tests/ui/cast/unsized-struct-cast.rs | 6 + tests/ui/cast/unsized-struct-cast.stderr | 9 + ...pat-crate-attributes-using-cfg_attr.stderr | 2 + tests/ui/check-cfg/values-target-json.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- .../closure_context/issue-26046-fn-mut.stderr | 2 +- .../issue-26046-fn-once.stderr | 2 +- .../match/if-let-guards-errors.e2018.stderr | 33 + .../match/if-let-guards-errors.e2021.stderr | 33 + .../match/if-let-guards-errors.rs | 37 + .../match/if-let-guards.rs | 55 + .../add_semicolon_non_block_closure.stderr | 2 +- .../ui/closures/binder/implicit-return.stderr | 4 +- .../ui/closures/binder/implicit-stuff.stderr | 4 +- tests/ui/closures/capture-unsized-by-move.rs | 10 + .../closures/capture-unsized-by-move.stderr | 14 + tests/ui/closures/capture-unsized-by-ref.rs | 10 + tests/ui/closures/closure-no-fn-1.stderr | 2 +- tests/ui/closures/closure-no-fn-2.stderr | 2 +- tests/ui/closures/closure-no-fn-3.stderr | 2 +- tests/ui/closures/closure-no-fn-4.stderr | 2 +- tests/ui/closures/closure-no-fn-5.stderr | 2 +- tests/ui/closures/closure-reform-bad.stderr | 2 +- .../closure_cap_coerce_many_fail.stderr | 20 +- tests/ui/closures/issue-112547.rs | 15 + tests/ui/closures/issue-112547.stderr | 23 + tests/ui/closures/issue-90871.stderr | 2 +- .../print/closure-print-generic-1.stderr | 2 +- .../print/closure-print-generic-2.stderr | 2 +- ...re-print-generic-trim-off-verbose-2.stderr | 2 +- .../closure-print-generic-verbose-1.stderr | 2 +- .../closure-print-generic-verbose-2.stderr | 2 +- .../print/closure-print-verbose.stderr | 2 +- .../ui/codegen/issue-79865-llvm-miscompile.rs | 38 + .../subtyping-enforces-type-equality.stderr | 1 - tests/ui/codemap_tests/tab.stderr | 2 +- .../coerce-expect-unsized-ascribed.stderr | 12 +- tests/ui/coercion/issue-53475.stderr | 7 +- ...e-overlap-downstream-inherent.next.stderr} | 4 +- ...nce-overlap-downstream-inherent.old.stderr | 23 + .../coherence-overlap-downstream-inherent.rs | 3 + ... coherence-overlap-downstream.next.stderr} | 6 +- .../coherence-overlap-downstream.old.stderr | 21 + .../coherence/coherence-overlap-downstream.rs | 3 + ...-overlap-issue-23516-inherent.next.stderr} | 2 +- ...ce-overlap-issue-23516-inherent.old.stderr | 14 + .../coherence-overlap-issue-23516-inherent.rs | 3 + ...coherence-overlap-issue-23516.next.stderr} | 2 +- .../coherence-overlap-issue-23516.old.stderr | 13 + .../coherence-overlap-issue-23516.rs | 3 + .../coherence-overlap-upstream.stderr | 2 +- .../coherence/coherence-wasm-bindgen.stderr | 14 +- ...-crate-ambiguity-causes-notes.next.stderr} | 13 +- ...er-crate-ambiguity-causes-notes.old.stderr | 17 + .../inter-crate-ambiguity-causes-notes.rs | 3 + ...rn-when-cycle-is-error-in-coherence.stderr | 13 +- tests/ui/compare-method/bad-self-type.stderr | 4 +- .../cfg-attr-syntax-validation.stderr | 1 + .../issue-33784.stderr | 4 +- .../adt_const_params/const_param_ty_bad.rs | 2 +- .../const_param_ty_bad.stderr | 4 +- .../const_param_ty_impl_no_structural_eq.rs | 2 + ...onst_param_ty_impl_no_structural_eq.stderr | 35 +- .../suggest_feature_only_when_possible.rs | 44 + .../suggest_feature_only_when_possible.stderr | 80 + .../assoc_const_eq_diagnostic.stderr | 1 + .../const-argument-if-length.full.stderr | 16 +- .../const-param-elided-lifetime.min.stderr | 10 +- ...ram-type-depends-on-const-param.min.stderr | 4 +- .../float-generic.simple.stderr | 1 - .../fn-const-param-call.min.stderr | 4 + .../fn-const-param-infer.min.stderr | 2 + ...ay-size-in-generic-struct-param.min.stderr | 2 +- .../generic_const_exprs/issue-80742.stderr | 2 +- ...ics-type_name-as-const-argument.min.stderr | 2 +- .../issues/issue-56445-1.min.stderr | 2 +- .../issues/issue-62878.min.stderr | 2 +- .../issues/issue-63322-forbid-dyn.min.stderr | 2 +- .../issues/issue-68615-adt.min.stderr | 2 +- .../issues/issue-68615-array.min.stderr | 2 +- .../issues/issue-71169.min.stderr | 2 +- .../issues/issue-71381.min.stderr | 4 + .../issues/issue-71382.min.stderr | 2 + .../issues/issue-71611.min.stderr | 2 + .../issues/issue-72352.min.stderr | 2 + .../issues/issue-73491.min.stderr | 2 +- ...tic-reference-array-const-param.min.stderr | 2 +- .../issues/issue-74101.min.stderr | 4 +- .../issues/issue-74255.min.stderr | 2 +- .../issues/issue-74950.min.stderr | 14 +- .../issues/issue-75047.min.stderr | 2 +- .../const-generics/issues/issue-83249.stderr | 15 +- .../lifetime-in-const-param.stderr | 2 +- .../min_const_generics/complex-types.stderr | 13 +- .../ui/const-generics/nested-type.min.stderr | 2 +- .../occurs-check/unused-substs-1.stderr | 2 +- .../projection-as-arg-const.stderr | 1 - .../raw-ptr-const-param-deref.min.stderr | 4 + .../raw-ptr-const-param.min.stderr | 2 + .../slice-const-param-mismatch.min.stderr | 4 +- .../std/const-generics-range.min.stderr | 12 +- ...te-const-param-static-reference.min.stderr | 2 +- .../type-dependent/issue-71348.min.stderr | 4 +- .../type-dependent/issue-71382.stderr | 2 + tests/ui/consts/const-adt-align-mismatch.rs | 2 +- tests/ui/consts/const-err-late.stderr | 2 + tests/ui/consts/const-eval/issue-44578.stderr | 1 + tests/ui/consts/const-eval/nrvo.rs | 3 +- .../const-eval/panic-assoc-never-type.stderr | 2 + .../ctfe-simple-loop.warn.stderr | 1 + .../const-eval/union-const-eval-field.rs | 2 - .../const-eval/union-const-eval-field.stderr | 8 +- .../ui/consts/const_in_pattern/issue-65466.rs | 3 +- .../const_in_pattern/issue-65466.stderr | 23 + .../const_in_pattern/reject_non_structural.rs | 5 +- .../reject_non_structural.stderr | 33 +- tests/ui/consts/enum-discr-type-err.stderr | 1 + tests/ui/consts/fn_trait_refs.stderr | 72 +- tests/ui/consts/invalid-union.32bit.stderr | 2 + tests/ui/consts/invalid-union.64bit.stderr | 2 + tests/ui/consts/issue-102117.stderr | 15 +- .../issue-17718-const-bad-values.stderr | 1 + tests/ui/consts/issue-67696-const-prop-ice.rs | 2 +- .../consts/miri_unleashed/assoc_const.stderr | 2 + .../miri_unleashed/assoc_const_2.stderr | 2 + .../uninhabited-const-issue-61744.stderr | 2 + .../ui/consts/unstable-const-fn-in-libcore.rs | 8 +- .../unstable-const-fn-in-libcore.stderr | 34 +- tests/ui/crate-loading/invalid-rlib.rs | 1 + tests/ui/crate-loading/invalid-rlib.stderr | 1 + tests/ui/debuginfo/sroa-fragment-debuginfo.rs | 2 +- .../deduplicate-diagnostics.duplicate.stderr | 4 + .../ui/deprecation/deprecation-sanity.stderr | 10 +- tests/ui/derives/deriving-bounds.stderr | 2 + .../deriving-meta-unknown-trait.stderr | 2 + tests/ui/derives/deriving-primitive.stderr | 2 + ...t_fail_parsing_on_invalid_options_1.stderr | 6 + .../auxiliary/doc-hidden-fields.rs | 6 + tests/ui/did_you_mean/bad-assoc-expr.stderr | 62 +- tests/ui/did_you_mean/bad-assoc-pat.stderr | 41 +- tests/ui/did_you_mean/bad-assoc-ty.stderr | 62 +- .../dont-suggest-doc-hidden-fields.rs | 38 + .../dont-suggest-doc-hidden-fields.stderr | 27 + .../dont-suggest-hygienic-fields.rs | 47 + .../dont-suggest-hygienic-fields.stderr | 50 + .../issue-93210-ignore-doc-hidden.rs | 24 - .../issue-93210-ignore-doc-hidden.stderr | 19 - .../dyn-keyword/dyn-2018-edition-lint.stderr | 4 + .../auxiliary/bad_main_functions.rs | 2 + ...orted_main_from_extern_crate_wrong_type.rs | 6 + ...d_main_from_extern_crate_wrong_type.stderr | 12 + tests/ui/error-codes/E0094.rs | 2 +- tests/ui/error-codes/E0132.stderr | 4 +- tests/ui/error-codes/E0282.rs | 2 +- tests/ui/error-codes/E0282.stderr | 6 +- tests/ui/error-codes/E0308.stderr | 8 +- tests/ui/error-codes/E0311.fixed | 2 +- tests/ui/error-codes/E0311.stderr | 20 +- tests/ui/error-codes/E0374.stderr | 9 +- tests/ui/error-codes/E0377.stderr | 6 +- tests/ui/error-codes/E0401.stderr | 14 +- tests/ui/error-codes/E0452.stderr | 6 + tests/ui/error-codes/E0453.stderr | 2 + tests/ui/error-codes/E0476.stderr | 4 +- tests/ui/error-codes/E0602.stderr | 2 + tests/ui/error-codes/E0647.stderr | 4 +- tests/ui/error-codes/E0719.stderr | 2 + tests/ui/error-codes/E0767.stderr | 2 +- tests/ui/error-codes/E0789.stderr | 2 + .../extern-flag/invalid-crate-name-dashed.rs | 10 + .../invalid-crate-name-dashed.stderr | 4 + .../invalid-crate-name-non-ascii.rs | 4 + .../invalid-crate-name-non-ascii.stderr | 2 + tests/ui/extern-flag/invalid-crate-name.rs | 4 + .../ui/extern-flag/invalid-crate-name.stderr | 2 + tests/ui/extern/extern-main-fn.stderr | 4 +- tests/ui/extern/extern-with-type-bounds.rs | 2 +- .../feature-gate-adt_const_params.stderr | 2 +- .../feature-gate-associated_type_bounds.rs | 6 +- ...feature-gate-associated_type_bounds.stderr | 6 +- ...ture-gate-impl_trait_in_fn_trait_return.rs | 4 +- ...-gate-impl_trait_in_fn_trait_return.stderr | 4 +- .../feature-gate-lint-reasons.stderr | 1 + ...gate-multiple_supertrait_upcastable.stderr | 4 + ...on_exhaustive_omitted_patterns_lint.stderr | 6 + .../feature-gate-proc_macro_byte_character.rs | 10 + ...ture-gate-proc_macro_byte_character.stderr | 12 + ...ate-return_position_impl_trait_in_trait.rs | 6 +- ...return_position_impl_trait_in_trait.stderr | 6 +- ...ature-gate-return_type_notation.cfg.stderr | 6 +- ...eature-gate-return_type_notation.no.stderr | 2 +- .../feature-gate-return_type_notation.rs | 1 + .../feature-gate-strict_provenance.stderr | 4 + .../feature-gate-test_unstable_lint.stderr | 2 + .../feature-gate-type_privacy_lints.stderr | 2 + .../issue-43106-gating-of-derive-2.stderr | 6 + tests/ui/fn/bad-main.stderr | 4 +- ...ied-bounds-unnorm-associated-type-5.stderr | 6 +- tests/ui/for/issue-20605.next.stderr | 12 +- tests/ui/foreign/foreign-fn-linkname.rs | 3 + .../fn-help-with-err.stderr | 4 +- tests/ui/generator/addassign-yield.rs | 3 - .../auto-trait-regions.drop_tracking.stderr | 55 - ...uto-trait-regions.drop_tracking_mir.stderr | 55 - tests/ui/generator/auto-trait-regions.rs | 3 - ...cking.stderr => auto-trait-regions.stderr} | 8 +- .../generator/borrowing.drop_tracking.stderr | 31 - .../borrowing.no_drop_tracking.stderr | 31 - tests/ui/generator/borrowing.rs | 4 - ...p_tracking_mir.stderr => borrowing.stderr} | 4 +- tests/ui/generator/clone-impl-async.stderr | 24 +- tests/ui/generator/clone-impl-static.stderr | 8 +- tests/ui/generator/clone-impl.stderr | 54 +- .../ui/generator/derived-drop-parent-expr.rs | 1 - tests/ui/generator/drop-control-flow.rs | 1 - .../generator/drop-track-addassign-yield.rs | 1 - .../ui/generator/drop-tracking-error-body.rs | 18 - .../generator/drop-tracking-error-body.stderr | 17 - ...ing-parent-expression.drop_tracking.stderr | 128 - ...-parent-expression.no_drop_tracking.stderr | 334 -- .../drop-tracking-parent-expression.rs | 11 +- ...=> drop-tracking-parent-expression.stderr} | 24 +- .../drop-tracking-yielding-in-match-guards.rs | 3 - tests/ui/generator/drop-yield-twice.stderr | 17 +- ...erator-yielding-or-returning-itself.stderr | 4 +- tests/ui/generator/issue-102645.rs | 2 - tests/ui/generator/issue-102645.stderr | 2 +- tests/ui/generator/issue-105084.rs | 12 +- ...racking_mir.stderr => issue-105084.stderr} | 18 +- ...sue-110929-generator-conflict-error-ice.rs | 1 - ...110929-generator-conflict-error-ice.stderr | 2 +- .../issue-57017.no_drop_tracking.stderr | 248 -- tests/ui/generator/issue-57017.rs | 13 +- .../issue-57478.no_drop_tracking.stderr | 31 - tests/ui/generator/issue-57478.rs | 7 +- .../issue-68112.drop_tracking.stderr | 66 - .../issue-68112.no_drop_tracking.stderr | 66 - tests/ui/generator/issue-68112.rs | 6 +- ...tracking_mir.stderr => issue-68112.stderr} | 18 +- tests/ui/generator/issue-93161.rs | 3 - .../not-send-sync.drop_tracking.stderr | 60 - .../not-send-sync.no_drop_tracking.stderr | 60 - tests/ui/generator/not-send-sync.rs | 3 - ...acking_mir.stderr => not-send-sync.stderr} | 16 +- .../parent-expression.drop_tracking.stderr | 128 - .../parent-expression.no_drop_tracking.stderr | 334 -- tests/ui/generator/parent-expression.rs | 9 - ...ng_mir.stderr => parent-expression.stderr} | 24 +- .../partial-drop.drop_tracking.stderr | 61 - .../partial-drop.no_drop_tracking.stderr | 61 - tests/ui/generator/partial-drop.rs | 15 +- ...rator-print-verbose-1.drop_tracking.stderr | 64 - ...or-print-verbose-1.no_drop_tracking.stderr | 64 - .../print/generator-print-verbose-1.rs | 3 - ...tderr => generator-print-verbose-1.stderr} | 18 +- ...rator-print-verbose-2.drop_tracking.stderr | 60 - ...or-print-verbose-2.no_drop_tracking.stderr | 60 - .../print/generator-print-verbose-2.rs | 3 - ...tderr => generator-print-verbose-2.stderr} | 16 +- .../print/generator-print-verbose-3.stderr | 2 +- tests/ui/generator/ref-upvar-not-send.stderr | 2 +- .../retain-resume-ref.drop_tracking.stderr | 13 - .../retain-resume-ref.no_drop_tracking.stderr | 13 - tests/ui/generator/retain-resume-ref.rs | 4 - ...ng_mir.stderr => retain-resume-ref.stderr} | 2 +- .../static-mut-reference-across-yield.rs | 4 +- .../generator/static-not-unpin.current.stderr | 4 +- .../ui/generator/static-not-unpin.next.stderr | 4 +- .../type-mismatch-signature-deduction.stderr | 2 +- .../unresolved-ct-var-drop-tracking.rs | 15 - .../unresolved-ct-var-drop-tracking.stderr | 78 - tests/ui/generator/unresolved-ct-var.rs | 5 - tests/ui/generator/unresolved-ct-var.stderr | 65 +- .../generator/unsized-capture-across-yield.rs | 22 + .../unsized-capture-across-yield.stderr | 23 + .../generator/unsized-local-across-yield.rs | 21 + .../unsized-local-across-yield.stderr | 21 + .../bugs/issue-100013.stderr | 30 - .../bugs/issue-91762.stderr | 5 +- .../gat-trait-path-missing-lifetime.stderr | 1 + .../issue-84931.stderr | 11 +- .../issue-90014-tait.stderr | 2 +- .../issue-91139.stderr | 2 + .../elided-lifetimes.stderr | 2 +- .../inference-failure.stderr | 2 +- .../unsatisfied-bounds.stderr | 2 + tests/ui/generics/issue-83556.rs | 4 + tests/ui/generics/issue-83556.stderr | 8 + ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 1 + .../trait-bounds/future.classic.stderr | 2 +- .../trait-bounds/hrtb-conflate-regions.stderr | 1 + .../trait-bounds/issue-30786.stderr | 18 +- .../trait-bounds/issue-59311.stderr | 2 +- .../trait-bounds/issue-62203-hrtb-ice.stderr | 8 +- .../ui/impl-trait/bound-normalization-fail.rs | 3 +- .../bound-normalization-fail.stderr | 16 +- .../impl-trait/capture-lifetime-not-in-hir.rs | 21 + .../capture-lifetime-not-in-hir.stderr | 14 + .../impl-trait/coherence-treats-tait-ambig.rs | 3 - ...err => coherence-treats-tait-ambig.stderr} | 2 +- .../impl-trait/cross-return-site-inference.rs | 4 +- .../cross-return-site-inference.stderr | 27 +- .../ui/impl-trait/feature-self-return-type.rs | 1 - .../feature-self-return-type.stderr | 6 +- ...lifetime-from-bare-trait-obj-114664.stderr | 2 + tests/ui/impl-trait/impl-subtyper.rs | 18 + tests/ui/impl-trait/impl-subtyper2.rs | 7 + .../in-trait/anonymize-binders-for-refine.rs | 13 + .../in-trait/assumed-wf-bounds-in-impl.rs | 1 + .../in-trait/default-body-with-rpit.rs | 1 + tests/ui/impl-trait/in-trait/default-body.rs | 1 + tests/ui/impl-trait/in-trait/early.rs | 1 + tests/ui/impl-trait/in-trait/refine.rs | 11 + tests/ui/impl-trait/in-trait/refine.stderr | 4 +- ...-hidden-types-self-implied-wf-via-param.rs | 26 + ...den-types-self-implied-wf-via-param.stderr | 16 + .../rpitit-hidden-types-self-implied-wf.rs | 23 + ...rpitit-hidden-types-self-implied-wf.stderr | 16 + .../in-trait/suggest-missing-item.fixed | 3 + .../in-trait/suggest-missing-item.rs | 3 + .../in-trait/suggest-missing-item.stderr | 6 +- .../issue-55872-2.drop_tracking.stderr | 8 - .../issue-55872-2.no_drop_tracking.stderr | 8 - tests/ui/impl-trait/issue-55872-2.rs | 5 +- ...acking_mir.stderr => issue-55872-2.stderr} | 6 +- tests/ui/impl-trait/issue-55872-3.stderr | 4 +- tests/ui/impl-trait/issue-99073.stderr | 2 +- tests/ui/impl-trait/issues/issue-54600.rs | 2 +- tests/ui/impl-trait/issues/issue-54600.stderr | 2 +- tests/ui/impl-trait/issues/issue-54840.rs | 2 +- tests/ui/impl-trait/issues/issue-54840.stderr | 2 +- tests/ui/impl-trait/issues/issue-58504.rs | 2 +- tests/ui/impl-trait/issues/issue-58504.stderr | 2 +- tests/ui/impl-trait/issues/issue-58956.rs | 4 +- tests/ui/impl-trait/issues/issue-58956.stderr | 4 +- tests/ui/impl-trait/issues/issue-62742.stderr | 5 +- tests/ui/impl-trait/issues/issue-70971.rs | 2 +- tests/ui/impl-trait/issues/issue-70971.stderr | 2 +- tests/ui/impl-trait/issues/issue-74282.stderr | 2 +- .../ui/impl-trait/issues/issue-78722-2.stderr | 2 +- tests/ui/impl-trait/issues/issue-78722.stderr | 2 +- tests/ui/impl-trait/issues/issue-79099.rs | 2 +- tests/ui/impl-trait/issues/issue-79099.stderr | 2 +- ...sue-83929-impl-trait-in-generic-default.rs | 4 +- ...83929-impl-trait-in-generic-default.stderr | 4 +- tests/ui/impl-trait/issues/issue-84073.stderr | 2 +- tests/ui/impl-trait/issues/issue-84919.rs | 2 +- tests/ui/impl-trait/issues/issue-84919.stderr | 2 +- tests/ui/impl-trait/issues/issue-86642.rs | 2 +- tests/ui/impl-trait/issues/issue-86642.stderr | 2 +- tests/ui/impl-trait/issues/issue-87295.rs | 2 +- tests/ui/impl-trait/issues/issue-87295.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 9 +- .../nested-return-type2-tait2.stderr | 2 +- .../nested-return-type2-tait3.stderr | 2 +- .../ui/impl-trait/nested-return-type4.stderr | 2 +- tests/ui/impl-trait/nested_impl_trait.rs | 2 +- tests/ui/impl-trait/nested_impl_trait.stderr | 2 +- .../impl-trait/normalize-tait-in-const.stderr | 25 +- .../opaque-cast-field-access-in-future.rs | 27 + .../opaque-cast-field-access-in-future.stderr | 11 + tests/ui/impl-trait/recursive-generator.rs | 1 - .../ui/impl-trait/recursive-generator.stderr | 15 +- ...l-trait-type-indirect.drop_tracking.stderr | 152 - ...rait-type-indirect.no_drop_tracking.stderr | 152 - .../recursive-impl-trait-type-indirect.rs | 4 - ...recursive-impl-trait-type-indirect.stderr} | 38 +- .../static-return-lifetime-infered.stderr | 4 +- .../type_parameters_captured.stderr | 7 +- .../impl-trait/unactionable_diagnostic.fixed | 2 +- .../ui/impl-trait/unactionable_diagnostic.rs | 2 +- .../impl-trait/unactionable_diagnostic.stderr | 5 +- tests/ui/impl-trait/where-allowed-2.stderr | 6 +- tests/ui/impl-trait/where-allowed.rs | 78 +- tests/ui/impl-trait/where-allowed.stderr | 78 +- tests/ui/imports/ambiguous-9.stderr | 1 + tests/ui/imports/issue-55457.stderr | 2 + tests/ui/indexing/index-help.stderr | 3 +- .../indexing/indexing-requires-a-uint.stderr | 3 +- .../cannot-infer-closure-circular.stderr | 3 + tests/ui/inference/issue-104649.stderr | 2 +- tests/ui/inference/issue-71584.rs | 1 + tests/ui/inference/issue-71584.stderr | 2 +- tests/ui/inference/issue-72690.stderr | 16 +- tests/ui/inference/multiple-impl-apply.rs | 48 + tests/ui/inference/multiple-impl-apply.stderr | 23 + .../inference/need_type_info/concrete-impl.rs | 2 - .../need_type_info/concrete-impl.stderr | 11 +- ...rrect-impl-trait-in-path-suggestion.stderr | 14 +- .../inference/question-mark-type-infer.stderr | 7 +- tests/ui/inline-const/promotion.rs | 22 + tests/ui/inline-const/promotion.stderr | 14 + tests/ui/integral-indexing.stderr | 24 +- .../intrinsics/const-eval-select-bad.stderr | 4 +- .../intrinsics/feature-gate-safe-intrinsic.rs | 6 + .../feature-gate-safe-intrinsic.stderr | 20 + tests/ui/intrinsics/intrinsic-alignment.rs | 3 +- .../ui/invalid_dispatch_from_dyn_impls.stderr | 28 +- tests/ui/issues/auxiliary/issue-111011.stderr | 2 +- tests/ui/issues/issue-12127.stderr | 2 +- tests/ui/issues/issue-12187-1.stderr | 4 +- tests/ui/issues/issue-12187-2.stderr | 4 +- tests/ui/issues/issue-16966.stderr | 13 +- tests/ui/issues/issue-17551.stderr | 2 +- tests/ui/issues/issue-22638.rs | 4 +- tests/ui/issues/issue-24036.stderr | 13 +- tests/ui/issues/issue-24446.stderr | 14 +- tests/ui/issues/issue-27042.stderr | 15 +- tests/ui/issues/issue-33571.stderr | 1 + tests/ui/issues/issue-34334.stderr | 3 +- tests/ui/issues/issue-40000.stderr | 1 + tests/ui/issues/issue-41880.stderr | 2 +- tests/ui/issues/issue-43355.stderr | 2 +- tests/ui/issues/issue-45801.stderr | 1 + tests/ui/issues/issue-46101.stderr | 2 + tests/ui/issues/issue-47715.rs | 8 +- tests/ui/issues/issue-47715.stderr | 8 +- tests/ui/issues/issue-48838.stderr | 2 +- tests/ui/issues/issue-50600.stderr | 2 +- tests/ui/issues/issue-50688.stderr | 2 +- tests/ui/issues/issue-50714-1.stderr | 4 +- tests/ui/issues/issue-51154.stderr | 2 +- tests/ui/issues/issue-53251.stderr | 1 + .../issue-66667-function-cmp-cycle.stderr | 6 +- ...e-66923-show-error-for-correct-call.stderr | 6 +- tests/ui/issues/issue-77919.stderr | 2 +- tests/ui/issues/issue-9575.stderr | 4 +- tests/ui/iterators/collect-into-slice.stderr | 20 +- .../iterators/invalid-iterator-chain.stderr | 6 +- tests/ui/kindck/kindck-nonsendable-1.stderr | 4 +- .../start_lang_item_args.argc.stderr | 8 +- .../start_lang_item_args.argv.stderr | 8 +- ...start_lang_item_args.argv_inner_ptr.stderr | 11 +- .../start_lang_item_args.main_args.stderr | 13 +- .../start_lang_item_args.main_ret.stderr | 13 +- .../start_lang_item_args.main_ty.stderr | 8 +- ...art_lang_item_args.missing_all_args.stderr | 9 +- .../start_lang_item_args.missing_ret.stderr | 10 +- ..._lang_item_args.missing_sigpipe_arg.stderr | 9 +- tests/ui/lang-items/start_lang_item_args.rs | 24 +- .../start_lang_item_args.sigpipe.stderr | 8 +- .../start_lang_item_args.start_ret.stderr | 8 +- .../start_lang_item_args.too_many_args.stderr | 9 +- .../start_lang_item_with_target_feature.rs | 19 + ...start_lang_item_with_target_feature.stderr | 11 + tests/ui/lifetimes/issue-105675.stderr | 1 + .../lifetime-doesnt-live-long-enough.stderr | 49 +- .../lifetime-errors/issue_74400.stderr | 7 +- ...roducing-and-adding-missing-lifetime.fixed | 2 +- ...oducing-and-adding-missing-lifetime.stderr | 20 +- .../lifetimes/unusual-rib-combinations.stderr | 4 +- tests/ui/limits/issue-55878.stderr | 1 + .../linkage-attr/unstable-flavor.bpf.stderr | 2 +- .../linkage-attr/unstable-flavor.ptx.stderr | 2 +- tests/ui/linkage-attr/unstable-flavor.rs | 8 +- tests/ui/lint/cli-unknown-force-warn.stderr | 2 + ...and-line-register-unknown-lint-tool.stderr | 1 + tests/ui/lint/crate_level_only_lint.stderr | 12 + tests/ui/lint/forbid-group-group-2.stderr | 8 + tests/ui/lint/forbid-group-member.stderr | 2 + tests/ui/lint/forbid-member-group.stderr | 2 + .../allowed-group-warn-by-default-lint.stderr | 2 + .../ui/lint/force-warn/cap-lints-allow.stderr | 2 + ...up-allowed-cli-warn-by-default-lint.stderr | 2 + .../lint-group-allowed-lint-group.stderr | 2 + ...-group-allowed-warn-by-default-lint.stderr | 2 + .../force-warn/warnings-lint-group.stderr | 2 + tests/ui/lint/invalid_from_utf8.rs | 27 + tests/ui/lint/invalid_from_utf8.stderr | 135 +- tests/ui/lint/issue-80988.stderr | 2 + .../large_assignments/box_rc_arc_allowed.rs} | 17 +- .../box_rc_arc_allowed.stderr | 23 + .../large_future.attribute.stderr | 23 + .../large_future.option.stderr | 23 + .../ui/lint/large_assignments/large_future.rs | 26 + tests/ui/lint/lint-forbid-attr.stderr | 2 + tests/ui/lint/lint-forbid-cmdline.stderr | 1 + tests/ui/lint/lint-malformed.stderr | 6 + .../ui/lint/lint-removed-cmdline-deny.stderr | 2 + tests/ui/lint/lint-removed-cmdline.stderr | 2 + .../ui/lint/lint-renamed-cmdline-deny.stderr | 2 + tests/ui/lint/lint-renamed-cmdline.stderr | 2 + .../ui/lint/lint-stability-deprecated.stderr | 6 + .../ui/lint/lint-unexported-no-mangle.stderr | 4 + .../lint-unknown-lint-cmdline-deny.stderr | 4 + .../ui/lint/lint-unknown-lint-cmdline.stderr | 4 + .../dedup.drop_tracking.stderr | 21 - .../dedup.no_drop_tracking.stderr | 33 - tests/ui/lint/must_not_suspend/dedup.rs | 8 +- ....drop_tracking_mir.stderr => dedup.stderr} | 7 +- tests/ui/lint/must_not_suspend/gated.stderr | 2 + .../must_not_suspend/ref-drop-tracking.rs | 30 - .../must_not_suspend/ref-drop-tracking.stderr | 27 - .../must_not_suspend/ref.drop_tracking.stderr | 27 - .../ref.no_drop_tracking.stderr | 27 - tests/ui/lint/must_not_suspend/ref.rs | 5 - ...ef.drop_tracking_mir.stderr => ref.stderr} | 8 +- .../trait.drop_tracking_mir.stderr | 37 - .../trait.no_drop_tracking.stderr | 37 - tests/ui/lint/must_not_suspend/trait.rs | 6 - ...rait.drop_tracking.stderr => trait.stderr} | 10 +- .../unit.drop_tracking_mir.stderr | 26 - .../unit.no_drop_tracking.stderr | 26 - tests/ui/lint/must_not_suspend/unit.rs | 4 +- ...{unit.drop_tracking.stderr => unit.stderr} | 8 +- .../warn.drop_tracking.stderr | 26 - .../warn.no_drop_tracking.stderr | 26 - tests/ui/lint/must_not_suspend/warn.rs | 7 +- ...n.drop_tracking_mir.stderr => warn.stderr} | 20 +- tests/ui/lint/noop-method-call.fixed | 13 + tests/ui/lint/noop-method-call.rs | 13 + tests/ui/lint/noop-method-call.stderr | 14 +- tests/ui/lint/reasons-erroneous.rs | 28 +- tests/ui/lint/reasons-erroneous.stderr | 94 +- tests/ui/lint/reference_casting.rs | 31 + tests/ui/lint/reference_casting.stderr | 119 +- tests/ui/lint/register-tool-lint.stderr | 1 + .../expect_unused_inside_impl_block.rs | 30 + .../expect_with_forbid.rs | 8 +- .../expect_with_forbid.stderr | 30 +- tests/ui/lint/trivial_casts.stderr | 2 +- tests/ui/lint/unaligned_references.rs | 23 + tests/ui/lint/unaligned_references.stderr | 52 +- tests/ui/loops/loop-break-value.rs | 63 + tests/ui/loops/loop-break-value.stderr | 153 +- .../ui/loops/loop-labeled-break-value.stderr | 39 +- .../ui/loops/loop-properly-diverging-2.stderr | 13 +- tests/ui/lub-glb/old-lub-glb-object.stderr | 1 + tests/ui/macros/builtin-std-paths-fail.stderr | 8 + .../ui/macros/meta-item-absolute-path.stderr | 2 + tests/ui/macros/stringify.rs | 1 + tests/ui/main-wrong-type.stderr | 4 +- .../overlapping-impl-1-modulo-regions.stderr | 7 +- ...rs => issue-72896-non-partial-eq-const.rs} | 3 +- .../issue-72896-non-partial-eq-const.stderr | 23 + ...od-ambig-one-trait-unknown-int-type.stderr | 2 +- tests/ui/methods/method-missing-call.stderr | 2 +- tests/ui/mismatched_types/issue-19109.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 14 +- .../mix-bundle-and-whole-archive-link-attr.rs | 11 - ...-bundle-and-whole-archive-link-attr.stderr | 4 - .../mix-bundle-and-whole-archive.rs | 8 - .../mix-bundle-and-whole-archive.stderr | 4 - .../modifiers-override.stderr | 2 + .../fallback-closure-wrap.fallback.stderr | 4 +- tests/ui/never_type/issue-52443.stderr | 10 +- .../never-from-impl-is-reserved.stderr | 2 +- ...lue-fallback-issue-66757.nofallback.stderr | 1 + ...ormed-projection-input-issue-102800.stderr | 1 + .../escape-argument-callee.stderr | 2 +- .../escape-argument.stderr | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 2 +- .../propagate-approximated-ref.stderr | 2 +- ...er-to-static-comparing-against-free.stderr | 4 +- ...oximated-shorter-to-static-no-bound.stderr | 2 +- ...mated-shorter-to-static-wrong-bound.stderr | 2 +- .../propagate-approximated-val.stderr | 2 +- .../propagate-despite-same-free-region.stderr | 2 +- ...ail-to-approximate-longer-no-bounds.stderr | 2 +- ...-to-approximate-longer-wrong-bounds.stderr | 2 +- .../propagate-from-trait-match.stderr | 5 +- .../return-wrong-bound-region.stderr | 2 +- tests/ui/nll/issue-54556-stephaneyfx.stderr | 2 +- tests/ui/nll/issue-97997.stderr | 1 + ...98589-closures-relate-named-regions.stderr | 8 +- tests/ui/nll/issue-98693.stderr | 7 +- .../min-choice-reject-ambiguous.stderr | 10 +- ...missing-universe-cause-issue-114907.stderr | 3 + .../impl-fn-ignore-binder-via-bottom.stderr | 2 + .../ty-outlives/impl-trait-outlives.stderr | 10 +- .../projection-implied-bounds.stderr | 7 +- .../projection-no-regions-closure.stderr | 22 +- .../projection-no-regions-fn.stderr | 22 +- .../projection-one-region-closure.stderr | 10 +- ...tion-two-region-trait-bound-closure.stderr | 12 +- ...ection-where-clause-env-wrong-bound.stderr | 6 +- ...ion-where-clause-env-wrong-lifetime.stderr | 6 +- .../projection-where-clause-none.stderr | 5 +- ...ram-closure-approximate-lower-bound.stderr | 8 +- ...m-closure-outlives-from-return-type.stderr | 10 +- ...-closure-outlives-from-where-clause.stderr | 10 +- .../nll/ty-outlives/ty-param-fn-body.stderr | 4 +- tests/ui/nll/ty-outlives/ty-param-fn.stderr | 10 +- .../nll/type-check-pointer-comparisons.stderr | 4 + .../user-annotations/normalization-2.stderr | 2 + .../normalization-infer.stderr | 49 +- tests/ui/no-send-res-ports.stderr | 4 +- tests/ui/not-clone-closure.stderr | 6 +- ...assoc_type_bounds_sized_unnecessary.stderr | 2 + ...ject-safety-supertrait-mentions-GAT.stderr | 8 +- .../ui/offset-of/offset-of-output-type.stderr | 2 +- tests/ui/on-unimplemented/impl-substs.stderr | 3 +- tests/ui/on-unimplemented/on-impl.stderr | 3 + tests/ui/on-unimplemented/slice-index.stderr | 3 +- tests/ui/or-patterns/missing-bindings.stderr | 84 +- .../panic-handler-bad-signature-1.rs | 7 +- .../panic-handler-bad-signature-1.stderr | 18 +- .../panic-handler-bad-signature-2.rs | 5 +- .../panic-handler-bad-signature-2.stderr | 12 +- .../panic-handler-bad-signature-3.rs | 2 +- .../panic-handler-bad-signature-3.stderr | 8 +- .../panic-handler-bad-signature-5.rs | 13 + .../panic-handler-bad-signature-5.stderr | 12 + .../panic-handler-with-target-feature.rs | 15 + .../panic-handler-with-target-feature.stderr | 11 + .../short-ice-remove-middle-frames-2.rs | 1 + ...hort-ice-remove-middle-frames-2.run.stderr | 2 +- .../panics/short-ice-remove-middle-frames.rs | 1 + .../short-ice-remove-middle-frames.run.stderr | 2 +- .../assoc-const-underscore-semantic-fail.rs | 0 ...ssoc-const-underscore-semantic-fail.stderr | 0 .../assoc-const-underscore-syntactic-pass.rs | 0 .../ui/parser/{ => assoc}/assoc-oddities-1.rs | 0 .../{ => assoc}/assoc-oddities-1.stderr | 0 .../ui/parser/{ => assoc}/assoc-oddities-2.rs | 0 .../{ => assoc}/assoc-oddities-2.stderr | 0 .../{ => assoc}/assoc-static-semantic-fail.rs | 0 .../assoc-static-semantic-fail.stderr | 0 .../assoc-static-syntactic-fail.rs | 0 .../assoc-static-syntactic-fail.stderr | 0 .../{ => assoc}/assoc-type-in-type-arg.rs | 0 .../{ => assoc}/assoc-type-in-type-arg.stderr | 0 ...ciated-types-project-from-hrtb-explicit.rs | 0 ...ed-types-project-from-hrtb-explicit.stderr | 0 .../parser/{ => attribute}/attr-bad-meta-2.rs | 0 .../{ => attribute}/attr-bad-meta-2.stderr | 0 .../parser/{ => attribute}/attr-bad-meta-3.rs | 0 .../{ => attribute}/attr-bad-meta-3.stderr | 0 .../parser/{ => attribute}/attr-bad-meta.rs | 0 .../{ => attribute}/attr-bad-meta.stderr | 0 .../parser/{ => attribute}/attr-before-eof.rs | 0 .../{ => attribute}/attr-before-eof.stderr | 0 .../{ => attribute}/attr-dangling-in-fn.rs | 0 .../attr-dangling-in-fn.stderr | 0 .../{ => attribute}/attr-dangling-in-mod.rs | 0 .../attr-dangling-in-mod.stderr | 0 .../attr-stmt-expr-attr-bad.rs | 0 .../attr-stmt-expr-attr-bad.stderr | 1 + .../{ => attribute}/attr-with-a-semicolon.rs | 0 .../attr-with-a-semicolon.stderr | 0 tests/ui/parser/{ => attribute}/attr.rs | 0 tests/ui/parser/{ => attribute}/attr.stderr | 0 ...bute-with-no-generics-in-parameter-list.rs | 0 ...-with-no-generics-in-parameter-list.stderr | 0 .../{ => attribute}/attrs-after-extern-mod.rs | 0 .../attrs-after-extern-mod.stderr | 0 .../break-in-unlabeled-block-in-macro.rs | 43 + .../break-in-unlabeled-block-in-macro.stderr | 69 + .../ui/parser/break-in-unlabeled-block.fixed | 11 + tests/ui/parser/break-in-unlabeled-block.rs | 11 + .../ui/parser/break-in-unlabeled-block.stderr | 27 + tests/ui/parser/expr-as-stmt.stderr | 2 +- tests/ui/parser/issues/issue-15980.rs | 3 - tests/ui/parser/issues/issue-15980.stderr | 13 +- tests/ui/parser/issues/issue-52496.stderr | 9 +- tests/ui/parser/issues/issue-84117.stderr | 3 + tests/ui/parser/issues/issue-89388.stderr | 7 +- tests/ui/parser/issues/issue-89396.fixed | 4 +- tests/ui/parser/issues/issue-89396.rs | 4 +- tests/ui/parser/issues/issue-89396.stderr | 4 +- .../issues/issue-98601-delimiter-error-1.rs | 9 + .../issue-98601-delimiter-error-1.stderr | 16 + ...-98601-delimiter-error-unexpected-close.rs | 5 + ...01-delimiter-error-unexpected-close.stderr | 14 + tests/ui/parser/macro/macro-repeat.stderr | 2 + tests/ui/parser/missing-fat-arrow.rs | 38 + tests/ui/parser/missing-fat-arrow.stderr | 78 + .../parser/recover-quantified-closure.stderr | 4 +- tests/ui/parser/removed-syntax-with-2.stderr | 5 +- ...truct-literal-restrictions-in-lamda.stderr | 2 +- .../borrowck-pat-ref-mut-and-ref.stderr | 2 + .../pattern/non-structural-match-types.stderr | 4 +- .../pattern/patkind-litrange-no-expr.stderr | 2 + .../pattern/slice-patterns-irrefutable.stderr | 3 + tests/ui/pattern/usefulness/floats.rs | 40 +- tests/ui/pattern/usefulness/floats.stderr | 52 +- tests/ui/print_type_sizes/async.stdout | 16 +- tests/ui/print_type_sizes/generator.stdout | 2 +- .../generator_discr_placement.stdout | 2 +- .../ui/privacy/effective_visibilities.stderr | 4 + .../effective_visibilities_full_priv.stderr | 2 + tests/ui/privacy/privacy1.stderr | 1 + .../ui/privacy/private-in-public-warn.stderr | 2 +- tests/ui/privacy/private-in-public.stderr | 2 +- tests/ui/privacy/where-priv-type.stderr | 7 +- .../where-pub-type-impls-priv-trait.stderr | 7 +- tests/ui/proc-macro/auxiliary/api/mod.rs | 1 + tests/ui/proc-macro/auxiliary/api/parse.rs | 4 + tests/ui/proc-macro/auxiliary/print-tokens.rs | 16 + tests/ui/proc-macro/issue-37788.stderr | 2 +- .../proc-macro/issue-75930-derive-cfg.stderr | 1 + tests/ui/proc-macro/literal-to-string.rs | 26 + tests/ui/proc-macro/literal-to-string.stdout | 107 + .../macro-namespace-reserved-2.stderr | 1 + .../pretty-print-hack-show.local.stderr | 6 + .../pretty-print-hack-show.remapped.stderr | 6 + tests/ui/proc-macro/resolve-error.stderr | 8 + .../ui/proc-macro/resolved-located-at.stderr | 2 +- tests/ui/proc-macro/span-preservation.stderr | 8 +- tests/ui/range/issue-54505-no-std.rs | 6 +- tests/ui/range/issue-54505-no-std.stderr | 14 +- tests/ui/recursion/issue-83150.stderr | 6 +- tests/ui/recursion_limit/empty.stderr | 2 + tests/ui/recursion_limit/invalid_digit.stderr | 2 + tests/ui/recursion_limit/overflow.stderr | 2 + .../closure-in-projection-issue-97405.stderr | 12 +- ...s-close-associated-type-into-object.stderr | 40 +- .../regions-close-object-into-object-4.stderr | 29 +- .../regions-close-object-into-object-5.stderr | 29 +- ...regions-close-over-type-parameter-1.stderr | 11 +- .../regions-close-param-into-object.stderr | 24 +- ...ons-implied-bounds-projection-gap-1.stderr | 5 +- ...regions-infer-bound-from-trait-self.stderr | 11 +- .../regions-infer-bound-from-trait.stderr | 8 +- tests/ui/repr/16-bit-repr-c-enum.rs | 2 +- tests/ui/repr/repr-align-assign.stderr | 4 + tests/ui/repr/repr-align.stderr | 12 + .../resolve/associated-fn-called-as-fn.stderr | 14 +- tests/ui/resolve/bad-expr-path.stderr | 4 +- tests/ui/resolve/bad-expr-path2.stderr | 4 +- ...ethod-in-self-not-available-in-assoc-fn.rs | 18 + ...d-in-self-not-available-in-assoc-fn.stderr | 41 + tests/ui/resolve/issue-103474.stderr | 2 +- tests/ui/resolve/issue-116164.rs | 19 + tests/ui/resolve/issue-116164.stderr | 14 + tests/ui/resolve/issue-14254.stderr | 98 +- tests/ui/resolve/issue-2356.stderr | 42 +- tests/ui/resolve/issue-60057.stderr | 12 +- .../resolve/resolve-assoc-suggestions.stderr | 21 +- .../resolve/resolve-inconsistent-names.stderr | 42 +- .../resolve-speculative-adjustment.stderr | 14 +- ...e-with-name-similar-to-struct-field.stderr | 26 +- .../unresolved_static_type_field.stderr | 5 +- tests/ui/return/return-struct.stderr | 4 +- .../ui/rfcs/rfc-1623-static/rfc1623-2.stderr | 1 + .../rfc-2091-track-caller/error-with-start.rs | 2 +- .../error-with-start.stderr | 4 +- .../dont-infer-static.stderr | 7 +- .../regions-enum-not-wf.stderr | 13 +- .../regions-struct-not-wf.stderr | 8 +- .../issue-108645-target-feature-on-start.rs | 2 +- ...ssue-108645-target-feature-on-start.stderr | 4 +- .../crate_name_nonascii_forbidden-2.rs | 6 - .../crate_name_nonascii_forbidden-2.stderr | 8 - ...-1.rs => crate_name_nonascii_forbidden.rs} | 0 ...r => crate_name_nonascii_forbidden.stderr} | 2 +- .../const-closure-parse-not-item.rs | 3 +- .../const-closure-parse-not-item.stderr | 8 + .../const-closure-trait-method-fail.stderr | 15 +- .../const-closure-trait-method.stderr | 15 +- .../const-closures.stderr | 49 +- .../const-bound-on-not-const-associated-fn.rs | 28 + ...st-bound-on-not-const-associated-fn.stderr | 26 + .../effects/infer-fallback.rs | 11 + .../issue-102156.stderr | 1 + .../super-traits-fail-2.nn.stderr | 2 + .../super-traits-fail-2.ny.stderr | 2 + .../super-traits-fail-3.nn.stderr | 2 + .../super-traits-fail-3.ny.stderr | 2 + .../tilde-const-and-const-params.rs | 9 +- .../tilde-const-and-const-params.stderr | 20 +- .../trait-where-clause.rs | 2 + .../trait-where-clause.stderr | 32 +- .../edition-lint-fully-qualified-paths.stderr | 1 + .../edition-lint-nested-empty-paths.stderr | 2 + .../edition-lint-nested-paths.stderr | 2 + tests/ui/rust-2018/edition-lint-paths.stderr | 2 + .../ui/rust-2018/trait-import-suggestions.rs | 2 +- .../uniform-paths/cross-crate.stderr | 1 + .../uniform-paths/prelude-fail-2.stderr | 2 + tests/ui/sanitize/cfg.rs | 3 +- ...patible-with-saniziter-kcfi.aarch64.stderr | 2 + ...mpatible-with-saniziter-kcfi.x86_64.stderr | 2 + ...arbitrary_self_types_needing_mut_pin.fixed | 3 +- ...rbitrary_self_types_needing_mut_pin.stderr | 10 +- tests/ui/self/class-missing-self.stderr | 9 +- tests/ui/simd/intrinsic/generic-elements.rs | 28 +- .../ui/simd/intrinsic/generic-elements.stderr | 80 +- .../monomorphize-shuffle-index.generic.stderr | 12 + tests/ui/simd/monomorphize-shuffle-index.rs | 28 +- ...borrowck-call-is-borrow-issue-12224.stderr | 2 +- tests/ui/span/issue-39698.stderr | 34 +- tests/ui/span/move-closure.stderr | 2 +- tests/ui/specialization/issue-52050.stderr | 10 +- .../specialization-default-types.stderr | 2 +- tests/ui/stats/hir-stats.stderr | 32 +- tests/ui/stats/meta-stats.rs | 7 + tests/ui/str/str-idx.stderr | 9 +- tests/ui/str/str-mut-idx.stderr | 9 +- tests/ui/structs-enums/rec-align-u32.rs | 2 +- tests/ui/structs-enums/rec-align-u64.rs | 3 +- .../assoc-const-without-self.stderr | 2 +- .../assoc-type-in-method-return.stderr | 7 +- tests/ui/suggestions/assoc_fn_without_self.rs | 8 + .../suggestions/assoc_fn_without_self.stderr | 49 +- ...rg-where-it-should-have-been-called.stderr | 8 +- .../auxiliary/extern-issue-98562.rs | 26 + tests/ui/suggestions/call-boxed.stderr | 4 +- .../expected-boxed-future-isnt-pinned.stderr | 2 +- ...rg-where-it-should-have-been-called.stderr | 4 +- .../fn-or-tuple-struct-without-args.stderr | 2 +- .../impl-trait-missing-lifetime.stderr | 6 +- tests/ui/suggestions/issue-101623.stderr | 3 +- tests/ui/suggestions/issue-61963.stderr | 5 + tests/ui/suggestions/issue-83892.stderr | 2 +- .../suggestions/issue-84973-blacklist.stderr | 4 +- tests/ui/suggestions/issue-98562.rs | 12 + tests/ui/suggestions/issue-98562.stderr | 11 + .../suggestions/lifetimes/issue-105544.fixed | 14 +- .../ui/suggestions/lifetimes/issue-105544.rs | 6 +- .../suggestions/lifetimes/issue-105544.stderr | 104 +- .../missing-lifetimes-in-signature-2.fixed | 7 +- .../missing-lifetimes-in-signature-2.rs | 7 +- .../missing-lifetimes-in-signature-2.stderr | 23 +- .../missing-lifetimes-in-signature.stderr | 101 +- .../lifetimes/type-param-bound-scope.fixed | 47 + .../lifetimes/type-param-bound-scope.rs | 47 + .../lifetimes/type-param-bound-scope.stderr | 71 + .../type-param-missing-lifetime.fixed | 52 + .../lifetimes/type-param-missing-lifetime.rs | 52 + .../type-param-missing-lifetime.stderr | 66 + tests/ui/suggestions/missing-assoc-fn.stderr | 2 +- .../missing-lifetime-specifier.stderr | 8 + tests/ui/suggestions/return-closures.stderr | 8 +- tests/ui/suggestions/slice-issue-87994.stderr | 8 +- .../suggestions/sugg-else-for-closure.stderr | 4 +- tests/ui/suggestions/suggest-box.stderr | 2 +- .../suggest-dereferencing-index.stderr | 3 +- .../suggest-impl-trait-lifetime.fixed | 3 +- .../suggest-impl-trait-lifetime.rs | 3 +- .../suggest-impl-trait-lifetime.stderr | 7 +- .../suggest-ret-on-async-w-late.fixed | 14 + .../suggest-ret-on-async-w-late.rs | 3 + .../suggest-ret-on-async-w-late.stderr | 4 +- tests/ui/suggestions/unnamable-types.stderr | 6 +- tests/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- .../tool-attributes-misplaced-1.stderr | 2 + tests/ui/tool_lints.stderr | 1 + .../impl-bound-with-references-error.stderr | 7 +- .../associated_type_bound/impl-is-shadowed.rs | 21 + tests/ui/traits/coercion-generic-bad.stderr | 1 + tests/ui/traits/copy-guessing.stderr | 2 +- ...arams-by-name-in-suggestion-issue-96292.rs | 4 +- ...s-by-name-in-suggestion-issue-96292.stderr | 16 +- .../traits/issue-33140-hack-boundaries.stderr | 2 +- tests/ui/traits/issue-38404.stderr | 1 + tests/ui/traits/issue-59029-1.stderr | 2 + tests/ui/traits/issue-77982.rs | 1 + tests/ui/traits/issue-77982.stderr | 32 +- .../issue-91949-hangs-on-recursion.stderr | 2 +- tests/ui/traits/issue-99875.stderr | 4 +- .../multidispatch-convert-ambig-dest.rs | 1 - .../multidispatch-convert-ambig-dest.stderr | 16 +- .../traits/new-solver/alias-bound-unsound.rs | 1 - .../new-solver/alias-bound-unsound.stderr | 40 +- .../alias_eq_substs_eq_not_intercrate.stderr | 2 + .../runaway-impl-candidate-selection.stderr | 11 +- tests/ui/traits/new-solver/async.fail.stderr | 2 +- .../new-solver/auto-with-drop_tracking_mir.rs | 2 +- .../new-solver/coherence/issue-102048.stderr | 12 +- ...trait_ref_is_knowable-norm-overflow.stderr | 6 + .../fixpoint-exponential-growth.rs | 3 +- .../fixpoint-exponential-growth.stderr | 11 +- .../cycles/fixpoint-rerun-all-cycle-heads.rs | 53 + .../fixpoint-rerun-all-cycle-heads.stderr | 10 + .../cycles/inductive-not-on-stack.rs | 2 +- .../cycles/inductive-not-on-stack.stderr | 15 +- .../dont-ice-on-assoc-projection.stderr | 2 +- ...eneralize-proj-new-universe-index-2.stderr | 15 +- .../traits/new-solver/generator.fail.stderr | 8 +- ...unnormalizable_candidate.self_infer.stderr | 14 +- .../overflow/exponential-trait-goals.rs | 3 +- .../overflow/exponential-trait-goals.stderr | 11 +- .../bad-sized-cond.stderr | 12 +- .../ui/traits/non_lifetime_binders/on-rpit.rs | 16 + .../non_lifetime_binders/on-rpit.stderr | 11 + ...ggest-non-existing-fully-qualified-path.rs | 4 +- ...t-non-existing-fully-qualified-path.stderr | 16 +- .../traits/suggest-fully-qualified-closure.rs | 2 +- .../suggest-fully-qualified-closure.stderr | 18 +- ...st-fully-qualified-path-with-adjustment.rs | 4 +- ...ully-qualified-path-with-adjustment.stderr | 32 +- ...fully-qualified-path-without-adjustment.rs | 4 +- ...y-qualified-path-without-adjustment.stderr | 36 +- tests/ui/traits/unsend-future.rs | 1 + tests/ui/traits/unsend-future.stderr | 4 +- tests/ui/try-block/try-block-bad-type.stderr | 1 + tests/ui/try-trait/bad-interconversion.stderr | 9 +- .../ui/tuple/tuple-struct-fields/test2.stderr | 2 + .../ui/tuple/tuple-struct-fields/test3.stderr | 2 + tests/ui/tuple/wrong_argument_ice-4.stderr | 2 +- ...ity-lint-ambiguous_associated_items.stderr | 1 + .../closure_wf_outlives.stderr | 7 +- .../cross_inference_pattern_bug.rs | 2 +- .../destructure_tait-ice-113594.rs | 19 + .../destructure_tait-layout_of-ice-113594.rs | 23 + ...eric_type_does_not_live_long_enough.stderr | 7 +- .../implied_lifetime_wf_check3.stderr | 7 +- .../implied_lifetime_wf_check4_static.stderr | 7 +- .../indirect-recursion-issue-112047.rs | 2 +- .../indirect-recursion-issue-112047.stderr | 18 +- .../type-alias-impl-trait/issue-63279.stderr | 4 +- .../type-alias-impl-trait/issue-94429.stderr | 2 +- .../nested-impl-trait-in-tait.rs | 9 + .../nested-impl-trait-in-tait.stderr | 47 + .../normalize-alias-type.rs | 32 + .../type-alias-impl-trait/tait-normalize.rs | 14 + .../type-alias-impl-trait-fn-type.rs | 2 +- .../type-alias-impl-trait-fn-type.stderr | 2 +- .../wf-in-associated-type.fail.stderr | 8 +- .../wf-nested.fail.stderr | 7 +- .../wf-nested.pass_sound.stderr | 7 +- tests/ui/type-inference/sort_by_key.stderr | 11 +- tests/ui/type/subtyping-opaque-type.rs | 19 + .../cannot_infer_local_or_vec.stderr | 2 +- .../point-at-inference-issue-116155.rs | 17 + .../point-at-inference-issue-116155.stderr | 18 + tests/ui/type/type-error-break-tail.stderr | 13 +- tests/ui/typeck/escaping_bound_vars.rs | 16 + tests/ui/typeck/escaping_bound_vars.stderr | 10 + tests/ui/typeck/issue-104513-ice.rs | 2 +- tests/ui/typeck/issue-104513-ice.stderr | 2 +- ...ssue-116473-ice-wrong-span-variant-args.rs | 96 + ...-116473-ice-wrong-span-variant-args.stderr | 255 ++ tests/ui/typeck/issue-31173.stderr | 12 +- ...e-57673-ice-on-deref-of-boxed-trait.stderr | 2 +- ...ue-90027-async-fn-return-suggestion.stderr | 2 +- tests/ui/typeck/issue-91267.stderr | 2 +- .../return_type_containing_closure.stderr | 2 +- ...ypeck-builtin-bound-type-parameters.stderr | 2 + .../typeck_type_placeholder_item.stderr | 2 +- ...ed-closures-static-call-wrong-trait.stderr | 4 +- tests/ui/unknown-lint-tool-name.stderr | 2 + .../deny-unstable-lint-command-line.stderr | 2 + .../deny-unstable-lint-inline.stderr | 2 + ...-unknown-unstable-lint-command-line.stderr | 2 + .../warn-unknown-unstable-lint-inline.stderr | 2 + tests/ui/use/use-super-global-path.stderr | 2 + tests/ui/wf/wf-fn-where-clause.stderr | 18 +- .../wf/wf-impl-associated-type-region.stderr | 4 +- tests/ui/wf/wf-in-fn-type-static.stderr | 14 +- tests/ui/wf/wf-in-obj-type-static.stderr | 7 +- .../wf/wf-outlives-ty-in-fn-or-trait.stderr | 8 +- .../wf/wf-trait-associated-type-region.stderr | 11 +- triagebot.toml | 13 +- x | 2 +- 2772 files changed, 51641 insertions(+), 33320 deletions(-) delete mode 100644 compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch create mode 100644 compiler/rustc_codegen_cranelift/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch create mode 100644 compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs delete mode 100644 compiler/rustc_hir_typeck/src/generator_interior/mod.rs create mode 100644 compiler/rustc_lint/src/async_fn_in_trait.rs create mode 100644 compiler/rustc_middle/src/hooks/mod.rs create mode 100644 compiler/rustc_mir_dataflow/src/debuginfo.rs create mode 100644 compiler/rustc_mir_transform/src/add_subtyping_projections.rs create mode 100644 compiler/rustc_mir_transform/src/gvn.rs delete mode 100644 compiler/rustc_serialize/src/collection_impls.rs delete mode 100644 compiler/rustc_target/src/spec/armv7_apple_ios.rs create mode 100644 compiler/rustc_target/src/spec/hurd_base.rs create mode 100644 compiler/rustc_target/src/spec/hurd_gnu_base.rs create mode 100644 compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs create mode 100644 compiler/rustc_trait_selection/src/solve/inspect/analyse.rs rename compiler/rustc_trait_selection/src/solve/{inspect.rs => inspect/build.rs} (76%) create mode 100644 compiler/rustc_trait_selection/src/solve/inspect/mod.rs delete mode 100644 compiler/rustc_trait_selection/src/solve/search_graph/cache.rs create mode 100644 compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs create mode 100644 compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs create mode 100644 compiler/stable_mir/Cargo.toml rename compiler/{rustc_smir => stable_mir}/README.md (100%) rename compiler/{rustc_smir => stable_mir}/rust-toolchain.toml (100%) rename compiler/{rustc_smir/src/stable_mir => stable_mir/src}/fold.rs (89%) rename compiler/{rustc_smir/src/stable_mir/mod.rs => stable_mir/src/lib.rs} (73%) rename compiler/{rustc_smir/src/stable_mir => stable_mir/src}/mir.rs (100%) rename compiler/{rustc_smir/src/stable_mir => stable_mir/src}/mir/body.rs (93%) rename compiler/{rustc_smir/src/stable_mir => stable_mir/src}/ty.rs (87%) rename compiler/{rustc_smir/src/stable_mir => stable_mir/src}/visitor.rs (90%) create mode 100644 library/std/src/os/aix/fs.rs create mode 100644 library/std/src/os/aix/mod.rs create mode 100644 library/std/src/os/aix/raw.rs create mode 100644 library/std/src/os/hurd/fs.rs create mode 100644 library/std/src/os/hurd/mod.rs create mode 100644 library/std/src/os/hurd/raw.rs create mode 100644 library/std/src/os/uefi/env.rs create mode 100644 library/std/src/os/uefi/mod.rs create mode 100644 library/std/src/sys/uefi/alloc.rs create mode 100644 library/std/src/sys/uefi/env.rs create mode 100644 library/std/src/sys/uefi/helpers.rs create mode 100644 library/std/src/sys/uefi/mod.rs create mode 100644 library/std/src/sys/uefi/os.rs create mode 100644 library/std/src/sys/uefi/path.rs create mode 100644 library/std/src/sys/uefi/stdio.rs create mode 100644 library/std/src/sys/uefi/tests.rs create mode 100644 rust-bors.toml delete mode 100644 src/bootstrap/CHANGELOG.md delete mode 100755 src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh delete mode 100755 src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh delete mode 100644 src/ci/docker/host-x86_64/wasm32/Dockerfile delete mode 100644 src/ci/docker/scripts/crosstool-ng-git.sh create mode 100644 src/doc/rustc/src/platform-support/hurd.md create mode 100644 src/doc/unstable-book/src/compiler-flags/link-native-libraries.md create mode 100644 src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs create mode 100644 src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs create mode 100644 src/tools/clippy/clippy_lints/src/manual_hash_one.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs create mode 100644 src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs create mode 100644 src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs create mode 100644 src/tools/clippy/tests/ui-toml/decimal_literal_representation/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.fixed create mode 100644 src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.rs create mode 100644 src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr create mode 100644 src/tools/clippy/tests/ui-toml/disallowed_script_idents/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.rs create mode 100644 src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_size/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.fixed create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.rs create mode 100644 src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr create mode 100644 src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs create mode 100644 src/tools/clippy/tests/ui-toml/explicit_iter_loop/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.fixed create mode 100644 src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.rs create mode 100644 src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.stderr create mode 100644 src/tools/clippy/tests/ui-toml/large_stack_frames/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.rs create mode 100644 src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr create mode 100644 src/tools/clippy/tests/ui-toml/large_types_passed_by_value/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.fixed create mode 100644 src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.rs create mode 100644 src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr create mode 100644 src/tools/clippy/tests/ui-toml/manual_let_else/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.fixed create mode 100644 src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.rs create mode 100644 src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr create mode 100644 src/tools/clippy/tests/ui-toml/path_ends_with_ext/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs create mode 100644 src/tools/clippy/tests/ui-toml/result_large_err/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.rs create mode 100644 src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.rs create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.fixed create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.rs create mode 100644 src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr create mode 100644 src/tools/clippy/tests/ui-toml/too_many_arguments/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.rs create mode 100644 src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr create mode 100644 src/tools/clippy/tests/ui-toml/type_complexity/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.rs create mode 100644 src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr create mode 100644 src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs create mode 100644 src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr delete mode 100644 src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/default/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/disabled/clippy.toml rename src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/{undocumented_unsafe_blocks.stderr => undocumented_unsafe_blocks.default.stderr} (83%) rename src/tools/clippy/tests/{ui/undocumented_unsafe_blocks.stderr => ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr} (74%) create mode 100644 src/tools/clippy/tests/ui-toml/unnecessary_box_returns/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.fixed create mode 100644 src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.rs create mode 100644 src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr create mode 100644 src/tools/clippy/tests/ui-toml/verbose_bit_mask/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.fixed create mode 100644 src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.rs create mode 100644 src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr create mode 100644 src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed create mode 100644 src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs create mode 100644 src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr create mode 100644 src/tools/clippy/tests/ui/into_iter_without_iter.rs create mode 100644 src/tools/clippy/tests/ui/into_iter_without_iter.stderr create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs delete mode 100644 src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs rename src/tools/clippy/tests/ui/items_after_test_module/{block_module.rs => root_module.fixed} (86%) create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/root_module.rs create mode 100644 src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr create mode 100644 src/tools/clippy/tests/ui/iter_without_into_iter.rs create mode 100644 src/tools/clippy/tests/ui/iter_without_into_iter.stderr create mode 100644 src/tools/clippy/tests/ui/manual_hash_one.fixed create mode 100644 src/tools/clippy/tests/ui/manual_hash_one.rs create mode 100644 src/tools/clippy/tests/ui/manual_hash_one.stderr create mode 100644 src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed create mode 100644 src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs create mode 100644 src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr create mode 100644 src/tools/clippy/tests/ui/path_ends_with_ext.fixed create mode 100644 src/tools/clippy/tests/ui/path_ends_with_ext.rs create mode 100644 src/tools/clippy/tests/ui/path_ends_with_ext.stderr create mode 100644 src/tools/clippy/tests/ui/redundant_as_str.fixed create mode 100644 src/tools/clippy/tests/ui/redundant_as_str.rs create mode 100644 src/tools/clippy/tests/ui/redundant_as_str.stderr delete mode 100644 src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs create mode 100644 src/tools/clippy/tests/ui/unnecessary_map_on_constructor.fixed create mode 100644 src/tools/clippy/tests/ui/unnecessary_map_on_constructor.rs create mode 100644 src/tools/clippy/tests/ui/unnecessary_map_on_constructor.stderr create mode 100644 src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock create mode 100644 src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml create mode 100644 src/tools/miri/bench-cargo-miri/invalidate/src/main.rs create mode 100644 src/tools/miri/src/borrow_tracker/tree_borrows/exhaustive.rs create mode 100644 src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs delete mode 100644 src/tools/miri/src/helpers/convert.rs delete mode 100644 src/tools/miri/src/shims/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/android/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/freebsd/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/dlsym.rs delete mode 100644 src/tools/miri/src/shims/unix/macos/dlsym.rs delete mode 100644 src/tools/miri/src/shims/windows/dlsym.rs create mode 100644 src/tools/miri/src/shims/x86/sse3.rs create mode 100644 src/tools/miri/src/shims/x86/ssse3.rs rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_main_terminate.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_main_terminate.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_too_few_args.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_too_few_args.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_too_many_args.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_create_too_many_args.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_detached.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_detached.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_joined.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_joined.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_main.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_main.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_multiple.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_multiple.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_self.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/libc_pthread_join_self.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/unwind_top_of_stack.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/unwind_top_of_stack.stderr (85%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/close_stdout.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/close_stdout.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/isolated_stdin.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/isolated_stdin.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/mkstemp_immutable_arg.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/mkstemp_immutable_arg.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/read_from_stdout.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/read_from_stdout.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/unix_open_missing_required_mode.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/unix_open_missing_required_mode.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/write_to_stdin.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/fs/write_to_stdin.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memchr_null.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memchr_null.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcmp_null.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcmp_null.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcmp_zero.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcmp_zero.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcpy_zero.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memcpy_zero.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memrchr_null.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/memrchr_null.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/mmap_invalid_dealloc.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/mmap_invalid_dealloc.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/mmap_use_after_munmap.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/mmap_use_after_munmap.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/munmap.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/munmap.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/munmap_partial.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/munmap_partial.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_cond_double_destroy.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_cond_double_destroy.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_condattr_double_destroy.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_condattr_double_destroy.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_NULL_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_default_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_default_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_destroy_locked.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_destroy_locked.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_double_destroy.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_double_destroy.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_normal_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_normal_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_wrong_owner.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutex_wrong_owner.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutexattr_double_destroy.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_mutexattr_double_destroy.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_destroy_read_locked.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_destroy_write_locked.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_double_destroy.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_double_destroy.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_read_wrong_owner.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_unlock_unlocked.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_read_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_write_deadlock.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_wrong_owner.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/tokio/sleep.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/tokio/sleep.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/unsupported_incomplete_function.rs (100%) rename src/tools/miri/tests/{fail => fail-dep}/unsupported_incomplete_function.stderr (100%) delete mode 100644 src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs delete mode 100644 src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr create mode 100644 src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs create mode 100644 src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr create mode 100644 src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs rename src/tools/miri/tests/fail/{both_borrows/retag_data_race_protected_read.stack.stderr => stacked_borrows/retag_data_race_protected_read.stderr} (100%) create mode 100644 src/tools/miri/tests/fail/tree_borrows/spurious_read.rs create mode 100644 src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr create mode 100644 src/tools/miri/tests/pass/function_calls/disable_abi_check.stderr create mode 100644 src/tools/miri/tests/pass/intrinsics-x86-avx512.rs create mode 100644 src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs create mode 100644 src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs create mode 100644 src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr create mode 100644 src/tools/miri/tests/pass/tree_borrows/spurious_read.rs create mode 100644 src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr create mode 100644 src/tools/opt-dist/src/utils/artifact_size.rs create mode 100644 tests/assembly/closure-inherit-target-feature.rs create mode 100644 tests/codegen/debug-fndef-size.rs create mode 100644 tests/codegen/issue-97217.rs create mode 100644 tests/codegen/unwind-landingpad-cold.rs create mode 100644 tests/codegen/unwind-landingpad-inline.rs create mode 100644 tests/codegen/vecdeque-nonempty-get-no-panic.rs create mode 100644 tests/coverage-map/unreachable.cov-map create mode 100644 tests/coverage-map/unreachable.rs create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff create mode 100644 tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs create mode 100644 tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff delete mode 100644 tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-abort.diff delete mode 100644 tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.cast.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.cast.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.references.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.references.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.rs create mode 100644 tests/mir-opt/gvn.slices.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.slices.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/ssa_unreachable_116212.rs create mode 100644 tests/run-coverage/unreachable.coverage create mode 100644 tests/run-coverage/unreachable.rs delete mode 100644 tests/run-make/issue-71519/Makefile delete mode 100644 tests/run-make/issue-71519/main.rs create mode 100644 tests/run-make/silly-file-names/Makefile create mode 100644 tests/run-make/silly-file-names/silly-file-names.rs create mode 100644 tests/run-make/silly-file-names/silly-file-names.run.stdout create mode 100644 tests/rustdoc-ui/issue-102467.rs create mode 100644 tests/rustdoc-ui/issue-102467.stderr rename tests/rustdoc/{issue-25001.rs => anchor-id-duplicate-method-name-25001.rs} (94%) rename tests/rustdoc/{issue-15169.rs => anchor-id-trait-method-15169.rs} (56%) rename tests/rustdoc/{issue-28478.rs => anchor-id-trait-tymethod-28478.rs} (92%) rename tests/rustdoc/{issue-20646.rs => assoc-type-bindings-20646.rs} (90%) create mode 100644 tests/rustdoc/auxiliary/enum-variant.rs rename tests/rustdoc/{issue-21474.rs => deduplicate-glob-import-impl-21474.rs} (73%) rename tests/rustdoc/{issue-22025.rs => deduplicate-trait-impl-22025.rs} (59%) rename tests/rustdoc/{issue-19190-2.rs => deref-methods-19190-foreign-type.rs} (77%) rename tests/rustdoc/{issue-19190-3.rs => deref-methods-19190-inline.rs} (90%) rename tests/rustdoc/{issue-19190.rs => deref-methods-19190.rs} (86%) rename tests/rustdoc/{issue-13698.rs => doc-hidden-method-13698.rs} (81%) rename tests/rustdoc/{issue-18199.rs => doc-test-attr-18199.rs} (79%) create mode 100644 tests/rustdoc/doctest-hide-empty-line-23106.rs rename tests/rustdoc/{issue-23744.rs => doctest-markdown-inline-parse-23744.rs} (76%) rename tests/rustdoc/{issue-25944.rs => doctest-multi-line-string-literal-25944.rs} (63%) rename tests/rustdoc/{issue-15347.rs => document-hidden-items-15347.rs} (61%) create mode 100644 tests/rustdoc/enum-variant-value.rs rename tests/rustdoc/{issue-22038.rs => extern-fn-22038.rs} (87%) rename tests/rustdoc/{issue-12834.rs => highlight-invalid-rust-12834.rs} (80%) rename tests/rustdoc/{issue-28927.rs => ice-reexport-crate-root-28927.rs} (65%) rename tests/rustdoc/{issue-19181.rs => ice-type-error-19181.rs} (68%) rename tests/rustdoc/{issue-21092.rs => impl-assoc-type-21092.rs} (72%) rename tests/rustdoc/{issue-20175.rs => impl-ref-20175.rs} (68%) rename tests/rustdoc/{issue-16265-1.rs => infinite-redirection-16265-1.rs} (71%) rename tests/rustdoc/{issue-16265-2.rs => infinite-redirection-16265-2.rs} (50%) rename tests/rustdoc/{issue-20727-2.rs => inline-assoc-type-20727-bindings.rs} (90%) rename tests/rustdoc/{issue-20727-3.rs => inline-assoc-type-20727-bounds-deref.rs} (90%) rename tests/rustdoc/{issue-20727-4.rs => inline-assoc-type-20727-bounds-index.rs} (95%) rename tests/rustdoc/{issue-20727.rs => inline-assoc-type-20727-bounds.rs} (90%) create mode 100644 tests/rustdoc/inline_cross/async-fn.rs create mode 100644 tests/rustdoc/inline_cross/auxiliary/async-fn.rs create mode 100644 tests/rustdoc/inline_cross/auxiliary/fn-type.rs rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-21801.rs (100%) rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-23207-1.rs (100%) rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-23207-2.rs (100%) rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-27362-aux.rs (100%) create mode 100644 tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs rename tests/rustdoc/{issue-27362.rs => inline_cross/const-fn-27362.rs} (81%) rename tests/rustdoc/{issue-23207.rs => inline_cross/deduplicate-inlined-items-23207.rs} (72%) create mode 100644 tests/rustdoc/inline_cross/fn-type.rs create mode 100644 tests/rustdoc/inline_cross/non_lifetime_binders.rs rename tests/rustdoc/{issue-21801.rs => inline_cross/sugar-closure-crate-21801.rs} (74%) delete mode 100644 tests/rustdoc/issue-23106.rs rename tests/rustdoc/{issue-23812.rs => macro-doc-comment-23812.rs} (89%) rename tests/rustdoc/{issue-16019.rs => macro-ice-16019.rs} (75%) rename tests/rustdoc/{issue-27862.rs => markdown-table-escape-pipe-27862.rs} (63%) rename tests/rustdoc/{issue-17476.rs => method-link-foreign-trait-impl-17476.rs} (76%) delete mode 100644 tests/rustdoc/no-crate-filter.rs rename tests/rustdoc/{issue-15318-3.rs => primitive-raw-pointer-dox-15318-3.rs} (61%) rename tests/rustdoc/{issue-15318.rs => primitive-raw-pointer-link-15318.rs} (76%) rename tests/rustdoc/{issue-15318-2.rs => primitive-raw-pointer-link-no-inlined-15318-2.rs} (75%) rename tests/rustdoc/{issue-23511.rs => search-index-primitive-inherent-method-23511.rs} (75%) rename tests/rustdoc/{issue-26606.rs => src-link-external-macro-26606.rs} (56%) rename tests/rustdoc/{issue-26995.rs => src-mod-path-absolute-26995.rs} (72%) rename tests/rustdoc/{issue-27759.rs => staged-api-feature-issue-27759.rs} (86%) rename tests/rustdoc/{issue-27104.rs => strip-priv-imports-pass-27104.rs} (77%) delete mode 100644 tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr delete mode 100644 tests/ui/async-await/async-await-let-else.drop-tracking.stderr delete mode 100644 tests/ui/async-await/async-await-let-else.drop_tracking.stderr delete mode 100644 tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr delete mode 100644 tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr rename tests/ui/async-await/{async-await-let-else.drop_tracking_mir.stderr => async-await-let-else.stderr} (83%) delete mode 100644 tests/ui/async-await/async-error-span.drop_tracking.stderr delete mode 100644 tests/ui/async-await/async-error-span.no_drop_tracking.stderr rename tests/ui/async-await/{async-error-span.drop_tracking_mir.stderr => async-error-span.stderr} (89%) delete mode 100644 tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr delete mode 100644 tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr rename tests/ui/async-await/{async-fn-nonsend.drop_tracking_mir.stderr => async-fn-nonsend.stderr} (88%) create mode 100644 tests/ui/async-await/awaiting-unsized-param.rs create mode 100644 tests/ui/async-await/awaiting-unsized-param.stderr create mode 100644 tests/ui/async-await/const-async-fn-in-main.rs create mode 100644 tests/ui/async-await/const-async-fn-in-main.stderr delete mode 100644 tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr delete mode 100644 tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr rename tests/ui/async-await/{drop-track-field-assign-nonsend.drop_tracking_mir.stderr => drop-track-field-assign-nonsend.stderr} (83%) delete mode 100644 tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr delete mode 100644 tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr rename tests/ui/async-await/{field-assign-nonsend.drop_tracking_mir.stderr => field-assign-nonsend.stderr} (86%) create mode 100644 tests/ui/async-await/in-trait/auxiliary/foreign-async-fn.rs create mode 100644 tests/ui/async-await/in-trait/send-on-async-fn-in-trait.fixed create mode 100644 tests/ui/async-await/in-trait/send-on-async-fn-in-trait.rs create mode 100644 tests/ui/async-await/in-trait/send-on-async-fn-in-trait.stderr create mode 100644 tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.rs create mode 100644 tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr create mode 100644 tests/ui/async-await/in-trait/warn.rs create mode 100644 tests/ui/async-await/in-trait/warn.stderr create mode 100644 tests/ui/async-await/issue-108572.fixed delete mode 100644 tests/ui/async-await/issue-61949-self-return-type.rs delete mode 100644 tests/ui/async-await/issue-61949-self-return-type.stderr delete mode 100644 tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr rename tests/ui/async-await/{issue-64130-1-sync.drop_tracking_mir.stderr => issue-64130-1-sync.stderr} (84%) delete mode 100644 tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr rename tests/ui/async-await/{issue-64130-2-send.drop_tracking_mir.stderr => issue-64130-2-send.stderr} (58%) delete mode 100644 tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr rename tests/ui/async-await/{issue-64130-3-other.drop_tracking_mir.stderr => issue-64130-3-other.stderr} (70%) delete mode 100644 tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr delete mode 100644 tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr rename tests/ui/async-await/{issue-67252-unnamed-future.drop_tracking_mir.stderr => issue-67252-unnamed-future.stderr} (69%) delete mode 100644 tests/ui/async-await/issue-68112.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-68112.no_drop_tracking.stderr rename tests/ui/async-await/{issue-68112.drop_tracking_mir.stderr => issue-68112.stderr} (90%) delete mode 100644 tests/ui/async-await/issue-70818.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-70818.no_drop_tracking.stderr rename tests/ui/async-await/{issue-70818.drop_tracking_mir.stderr => issue-70818.stderr} (90%) delete mode 100644 tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr rename tests/ui/async-await/{issue-70935-complex-spans.drop_tracking_mir.stderr => issue-70935-complex-spans.stderr} (85%) delete mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr delete mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr delete mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.rs delete mode 100644 tests/ui/async-await/issue-86507.drop_tracking_mir.stderr delete mode 100644 tests/ui/async-await/issue-86507.no_drop_tracking.stderr rename tests/ui/async-await/{issue-86507.drop_tracking.stderr => issue-86507.stderr} (80%) delete mode 100644 tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr delete mode 100644 tests/ui/async-await/issues/issue-78600.stderr delete mode 100644 tests/ui/async-await/large_moves.attribute.stderr delete mode 100644 tests/ui/async-await/large_moves.option.stderr delete mode 100644 tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr delete mode 100644 tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr rename tests/ui/async-await/{mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr => mutually-recursive-async-impl-trait-type.stderr} (75%) delete mode 100644 tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr rename tests/ui/async-await/{partial-drop-partial-reinit.drop_tracking.stderr => partial-drop-partial-reinit.stderr} (73%) delete mode 100644 tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr delete mode 100644 tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr rename tests/ui/async-await/{recursive-async-impl-trait-type.drop_tracking_mir.stderr => recursive-async-impl-trait-type.stderr} (77%) delete mode 100644 tests/ui/async-await/unresolved_type_param.drop_tracking.stderr delete mode 100644 tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr rename tests/ui/async-await/{unresolved_type_param.drop_tracking_mir.stderr => unresolved_type_param.stderr} (89%) create mode 100644 tests/ui/async-await/unsized-across-await.rs create mode 100644 tests/ui/async-await/unsized-across-await.stderr create mode 100644 tests/ui/auto-traits/pre-cfg.rs create mode 100644 tests/ui/auto-traits/pre-cfg.stderr delete mode 100644 tests/ui/borrowck/async-reference-generality.stderr delete mode 100644 tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs delete mode 100644 tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr create mode 100644 tests/ui/cast/unsized-struct-cast.rs create mode 100644 tests/ui/cast/unsized-struct-cast.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2018.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2021.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/if-let-guards.rs create mode 100644 tests/ui/closures/capture-unsized-by-move.rs create mode 100644 tests/ui/closures/capture-unsized-by-move.stderr create mode 100644 tests/ui/closures/capture-unsized-by-ref.rs create mode 100644 tests/ui/closures/issue-112547.rs create mode 100644 tests/ui/closures/issue-112547.stderr create mode 100644 tests/ui/codegen/issue-79865-llvm-miscompile.rs delete mode 100644 tests/ui/codegen/subtyping-enforces-type-equality.stderr rename tests/ui/coherence/{coherence-overlap-downstream-inherent.stderr => coherence-overlap-downstream-inherent.next.stderr} (87%) create mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream.stderr => coherence-overlap-downstream.next.stderr} (79%) create mode 100644 tests/ui/coherence/coherence-overlap-downstream.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516-inherent.stderr => coherence-overlap-issue-23516-inherent.next.stderr} (89%) create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516.stderr => coherence-overlap-issue-23516.next.stderr} (90%) create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.old.stderr rename tests/ui/coherence/{inter-crate-ambiguity-causes-notes.stderr => inter-crate-ambiguity-causes-notes.next.stderr} (51%) create mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr create mode 100644 tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs create mode 100644 tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr create mode 100644 tests/ui/consts/const_in_pattern/issue-65466.stderr create mode 100644 tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs create mode 100644 tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs create mode 100644 tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr create mode 100644 tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs create mode 100644 tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr delete mode 100644 tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs delete mode 100644 tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr create mode 100644 tests/ui/entry-point/auxiliary/bad_main_functions.rs create mode 100644 tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs create mode 100644 tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr create mode 100644 tests/ui/extern-flag/invalid-crate-name-dashed.rs create mode 100644 tests/ui/extern-flag/invalid-crate-name-dashed.stderr create mode 100644 tests/ui/extern-flag/invalid-crate-name-non-ascii.rs create mode 100644 tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr create mode 100644 tests/ui/extern-flag/invalid-crate-name.rs create mode 100644 tests/ui/extern-flag/invalid-crate-name.stderr create mode 100644 tests/ui/feature-gates/feature-gate-proc_macro_byte_character.rs create mode 100644 tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr delete mode 100644 tests/ui/generator/auto-trait-regions.drop_tracking.stderr delete mode 100644 tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr rename tests/ui/generator/{auto-trait-regions.no_drop_tracking.stderr => auto-trait-regions.stderr} (92%) delete mode 100644 tests/ui/generator/borrowing.drop_tracking.stderr delete mode 100644 tests/ui/generator/borrowing.no_drop_tracking.stderr rename tests/ui/generator/{borrowing.drop_tracking_mir.stderr => borrowing.stderr} (96%) delete mode 100644 tests/ui/generator/drop-tracking-error-body.rs delete mode 100644 tests/ui/generator/drop-tracking-error-body.stderr delete mode 100644 tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr delete mode 100644 tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr rename tests/ui/generator/{drop-tracking-parent-expression.drop_tracking_mir.stderr => drop-tracking-parent-expression.stderr} (84%) rename tests/ui/generator/{issue-105084.drop_tracking_mir.stderr => issue-105084.stderr} (72%) delete mode 100644 tests/ui/generator/issue-57017.no_drop_tracking.stderr delete mode 100644 tests/ui/generator/issue-57478.no_drop_tracking.stderr delete mode 100644 tests/ui/generator/issue-68112.drop_tracking.stderr delete mode 100644 tests/ui/generator/issue-68112.no_drop_tracking.stderr rename tests/ui/generator/{issue-68112.drop_tracking_mir.stderr => issue-68112.stderr} (89%) delete mode 100644 tests/ui/generator/not-send-sync.drop_tracking.stderr delete mode 100644 tests/ui/generator/not-send-sync.no_drop_tracking.stderr rename tests/ui/generator/{not-send-sync.drop_tracking_mir.stderr => not-send-sync.stderr} (72%) delete mode 100644 tests/ui/generator/parent-expression.drop_tracking.stderr delete mode 100644 tests/ui/generator/parent-expression.no_drop_tracking.stderr rename tests/ui/generator/{parent-expression.drop_tracking_mir.stderr => parent-expression.stderr} (86%) delete mode 100644 tests/ui/generator/partial-drop.drop_tracking.stderr delete mode 100644 tests/ui/generator/partial-drop.no_drop_tracking.stderr delete mode 100644 tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr delete mode 100644 tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr rename tests/ui/generator/print/{generator-print-verbose-1.drop_tracking_mir.stderr => generator-print-verbose-1.stderr} (86%) delete mode 100644 tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr delete mode 100644 tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr rename tests/ui/generator/print/{generator-print-verbose-2.drop_tracking_mir.stderr => generator-print-verbose-2.stderr} (68%) delete mode 100644 tests/ui/generator/retain-resume-ref.drop_tracking.stderr delete mode 100644 tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr rename tests/ui/generator/{retain-resume-ref.drop_tracking_mir.stderr => retain-resume-ref.stderr} (93%) delete mode 100644 tests/ui/generator/unresolved-ct-var-drop-tracking.rs delete mode 100644 tests/ui/generator/unresolved-ct-var-drop-tracking.stderr create mode 100644 tests/ui/generator/unsized-capture-across-yield.rs create mode 100644 tests/ui/generator/unsized-capture-across-yield.stderr create mode 100644 tests/ui/generator/unsized-local-across-yield.rs create mode 100644 tests/ui/generator/unsized-local-across-yield.stderr create mode 100644 tests/ui/generics/issue-83556.rs create mode 100644 tests/ui/generics/issue-83556.stderr create mode 100644 tests/ui/impl-trait/capture-lifetime-not-in-hir.rs create mode 100644 tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr rename tests/ui/impl-trait/{coherence-treats-tait-ambig.next.stderr => coherence-treats-tait-ambig.stderr} (88%) create mode 100644 tests/ui/impl-trait/impl-subtyper.rs create mode 100644 tests/ui/impl-trait/impl-subtyper2.rs create mode 100644 tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs create mode 100644 tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs create mode 100644 tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr create mode 100644 tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.rs create mode 100644 tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr delete mode 100644 tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr delete mode 100644 tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr rename tests/ui/impl-trait/{issue-55872-2.drop_tracking_mir.stderr => issue-55872-2.stderr} (71%) create mode 100644 tests/ui/impl-trait/opaque-cast-field-access-in-future.rs create mode 100644 tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr delete mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr delete mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr rename tests/ui/impl-trait/{recursive-impl-trait-type-indirect.drop_tracking_mir.stderr => recursive-impl-trait-type-indirect.stderr} (74%) create mode 100644 tests/ui/inference/multiple-impl-apply.rs create mode 100644 tests/ui/inference/multiple-impl-apply.stderr create mode 100644 tests/ui/inline-const/promotion.rs create mode 100644 tests/ui/inline-const/promotion.stderr create mode 100644 tests/ui/intrinsics/feature-gate-safe-intrinsic.rs create mode 100644 tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr create mode 100644 tests/ui/lang-items/start_lang_item_with_target_feature.rs create mode 100644 tests/ui/lang-items/start_lang_item_with_target_feature.stderr rename tests/ui/{async-await/large_moves.rs => lint/large_assignments/box_rc_arc_allowed.rs} (57%) create mode 100644 tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr create mode 100644 tests/ui/lint/large_assignments/large_future.attribute.stderr create mode 100644 tests/ui/lint/large_assignments/large_future.option.stderr create mode 100644 tests/ui/lint/large_assignments/large_future.rs delete mode 100644 tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr delete mode 100644 tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr rename tests/ui/lint/must_not_suspend/{dedup.drop_tracking_mir.stderr => dedup.stderr} (86%) delete mode 100644 tests/ui/lint/must_not_suspend/ref-drop-tracking.rs delete mode 100644 tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr delete mode 100644 tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr delete mode 100644 tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr rename tests/ui/lint/must_not_suspend/{ref.drop_tracking_mir.stderr => ref.stderr} (87%) delete mode 100644 tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr delete mode 100644 tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr rename tests/ui/lint/must_not_suspend/{trait.drop_tracking.stderr => trait.stderr} (88%) delete mode 100644 tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr delete mode 100644 tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr rename tests/ui/lint/must_not_suspend/{unit.drop_tracking.stderr => unit.stderr} (86%) delete mode 100644 tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr delete mode 100644 tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr rename tests/ui/lint/must_not_suspend/{warn.drop_tracking_mir.stderr => warn.stderr} (64%) create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs rename tests/ui/match/{issue-72896.rs => issue-72896-non-partial-eq-const.rs} (78%) create mode 100644 tests/ui/match/issue-72896-non-partial-eq-const.stderr delete mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs delete mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr delete mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs delete mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-5.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-5.stderr create mode 100644 tests/ui/panic-handler/panic-handler-with-target-feature.rs create mode 100644 tests/ui/panic-handler/panic-handler-with-target-feature.stderr rename tests/ui/parser/{ => assoc}/assoc-const-underscore-semantic-fail.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-const-underscore-semantic-fail.stderr (100%) rename tests/ui/parser/{ => assoc}/assoc-const-underscore-syntactic-pass.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-oddities-1.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-oddities-1.stderr (100%) rename tests/ui/parser/{ => assoc}/assoc-oddities-2.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-oddities-2.stderr (100%) rename tests/ui/parser/{ => assoc}/assoc-static-semantic-fail.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-static-semantic-fail.stderr (100%) rename tests/ui/parser/{ => assoc}/assoc-static-syntactic-fail.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-static-syntactic-fail.stderr (100%) rename tests/ui/parser/{ => assoc}/assoc-type-in-type-arg.rs (100%) rename tests/ui/parser/{ => assoc}/assoc-type-in-type-arg.stderr (100%) rename tests/ui/parser/{ => assoc}/associated-types-project-from-hrtb-explicit.rs (100%) rename tests/ui/parser/{ => assoc}/associated-types-project-from-hrtb-explicit.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-2.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-2.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-3.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-3.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-before-eof.rs (100%) rename tests/ui/parser/{ => attribute}/attr-before-eof.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-fn.rs (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-fn.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-mod.rs (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-mod.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.rs (100%) rename tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.stderr (99%) rename tests/ui/parser/{ => attribute}/attr-with-a-semicolon.rs (100%) rename tests/ui/parser/{ => attribute}/attr-with-a-semicolon.stderr (100%) rename tests/ui/parser/{ => attribute}/attr.rs (100%) rename tests/ui/parser/{ => attribute}/attr.stderr (100%) rename tests/ui/parser/{ => attribute}/attribute-with-no-generics-in-parameter-list.rs (100%) rename tests/ui/parser/{ => attribute}/attribute-with-no-generics-in-parameter-list.stderr (100%) rename tests/ui/parser/{ => attribute}/attrs-after-extern-mod.rs (100%) rename tests/ui/parser/{ => attribute}/attrs-after-extern-mod.stderr (100%) create mode 100644 tests/ui/parser/break-in-unlabeled-block-in-macro.rs create mode 100644 tests/ui/parser/break-in-unlabeled-block-in-macro.stderr create mode 100644 tests/ui/parser/break-in-unlabeled-block.fixed create mode 100644 tests/ui/parser/break-in-unlabeled-block.rs create mode 100644 tests/ui/parser/break-in-unlabeled-block.stderr create mode 100644 tests/ui/parser/issues/issue-98601-delimiter-error-1.rs create mode 100644 tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr create mode 100644 tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.rs create mode 100644 tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr create mode 100644 tests/ui/parser/missing-fat-arrow.rs create mode 100644 tests/ui/parser/missing-fat-arrow.stderr create mode 100644 tests/ui/proc-macro/auxiliary/print-tokens.rs create mode 100644 tests/ui/proc-macro/literal-to-string.rs create mode 100644 tests/ui/proc-macro/literal-to-string.stdout create mode 100644 tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs create mode 100644 tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr create mode 100644 tests/ui/resolve/issue-116164.rs create mode 100644 tests/ui/resolve/issue-116164.stderr delete mode 100644 tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs delete mode 100644 tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr rename tests/ui/rfcs/rfc-2457-non-ascii-idents/{crate_name_nonascii_forbidden-1.rs => crate_name_nonascii_forbidden.rs} (100%) rename tests/ui/rfcs/rfc-2457-non-ascii-idents/{crate_name_nonascii_forbidden-1.stderr => crate_name_nonascii_forbidden.stderr} (75%) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs create mode 100644 tests/ui/simd/monomorphize-shuffle-index.generic.stderr create mode 100644 tests/ui/stats/meta-stats.rs create mode 100644 tests/ui/suggestions/auxiliary/extern-issue-98562.rs create mode 100644 tests/ui/suggestions/issue-98562.rs create mode 100644 tests/ui/suggestions/issue-98562.stderr create mode 100644 tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed create mode 100644 tests/ui/suggestions/lifetimes/type-param-bound-scope.rs create mode 100644 tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr create mode 100644 tests/ui/suggestions/lifetimes/type-param-missing-lifetime.fixed create mode 100644 tests/ui/suggestions/lifetimes/type-param-missing-lifetime.rs create mode 100644 tests/ui/suggestions/lifetimes/type-param-missing-lifetime.stderr create mode 100644 tests/ui/suggestions/suggest-ret-on-async-w-late.fixed create mode 100644 tests/ui/traits/associated_type_bound/impl-is-shadowed.rs create mode 100644 tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs create mode 100644 tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/on-rpit.rs create mode 100644 tests/ui/traits/non_lifetime_binders/on-rpit.stderr create mode 100644 tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs create mode 100644 tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr create mode 100644 tests/ui/type-alias-impl-trait/normalize-alias-type.rs create mode 100644 tests/ui/type-alias-impl-trait/tait-normalize.rs create mode 100644 tests/ui/type/subtyping-opaque-type.rs create mode 100644 tests/ui/type/type-check/point-at-inference-issue-116155.rs create mode 100644 tests/ui/type/type-check/point-at-inference-issue-116155.stderr create mode 100644 tests/ui/typeck/escaping_bound_vars.rs create mode 100644 tests/ui/typeck/escaping_bound_vars.stderr create mode 100644 tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs create mode 100644 tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 618a26958eede..8c207e7ea115c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,7 @@ name: CI - auto - try - try-perf + - automation/bors/try - master pull_request: branches: @@ -264,9 +265,6 @@ jobs: - name: test-various os: ubuntu-20.04-8core-32gb env: {} - - name: wasm32 - os: ubuntu-20.04-8core-32gb - env: {} - name: x86_64-gnu os: ubuntu-20.04-4core-16gb env: {} @@ -305,7 +303,7 @@ jobs: SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 @@ -317,7 +315,7 @@ jobs: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 @@ -328,8 +326,8 @@ jobs: SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps" RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 + MACOSX_STD_DEPLOYMENT_TARGET: 10.12 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -339,8 +337,8 @@ jobs: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 + MACOSX_STD_DEPLOYMENT_TARGET: 10.12 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -542,7 +540,7 @@ jobs: ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" + if: "github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))" strategy: matrix: include: diff --git a/.mailmap b/.mailmap index 21e1adb43cff9..26d6be9f0c600 100644 --- a/.mailmap +++ b/.mailmap @@ -429,6 +429,8 @@ Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> nils <48135649+Nilstrieb Nif Ward Nika Layzell NODA Kai +Oğuz Ağcayazı +Oğuz Ağcayazı oliver <16816606+o752d@users.noreply.github.com> Oliver Middleton Oliver Scherer diff --git a/.reuse/dep5 b/.reuse/dep5 index 5546a7cf39112..245ed2659f91f 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -25,6 +25,7 @@ Files: compiler/* README.md RELEASES.md rustfmt.toml + rust-bors.toml triagebot.toml x x.ps1 diff --git a/Cargo.lock b/Cargo.lock index d9aaedb85443f..082bb4be93c0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,16 +118,15 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -157,9 +156,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -291,9 +290,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" @@ -392,7 +391,7 @@ dependencies = [ name = "cargo-miri" version = "0.1.0" dependencies = [ - "cargo_metadata", + "cargo_metadata 0.18.0", "directories", "rustc-build-sysroot", "rustc_tools_util", @@ -424,6 +423,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo_metadata" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cargotest2" version = "0.1.0" @@ -459,25 +472,23 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.10" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" +checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.10" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" +checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" dependencies = [ "anstream", "anstyle", "clap_lex", - "once_cell", "strsim", "terminal_size", ] @@ -493,9 +504,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", @@ -511,11 +522,12 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.74" +version = "0.1.75" dependencies = [ + "anstream", "clippy_lints", "clippy_utils", - "derive-new", + "color-print", "filetime", "futures", "if_chain", @@ -550,10 +562,10 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.74" +version = "0.1.75" dependencies = [ "arrayvec", - "cargo_metadata", + "cargo_metadata 0.15.4", "clippy_utils", "declare_clippy_lint", "if_chain", @@ -570,11 +582,12 @@ dependencies = [ "unicode-normalization", "unicode-script", "url", + "walkdir", ] [[package]] name = "clippy_utils" -version = "0.1.74" +version = "0.1.75" dependencies = [ "arrayvec", "if_chain", @@ -607,6 +620,27 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "color-print" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d" +dependencies = [ + "color-print-proc-macro", +] + +[[package]] +name = "color-print-proc-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f" +dependencies = [ + "nom", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "color-spantrace" version = "0.2.0" @@ -937,24 +971,13 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.74" +version = "0.1.75" dependencies = [ "itertools", "quote", "syn 2.0.29", ] -[[package]] -name = "derive-new" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive_builder" version = "0.12.0" @@ -1029,11 +1052,11 @@ dependencies = [ [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1042,7 +1065,7 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", ] [[package]] @@ -1066,6 +1089,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1253,12 +1288,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "field-offset" @@ -1993,17 +2025,6 @@ dependencies = [ "unic-langid", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" version = "2.7.2" @@ -2017,7 +2038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.2", + "rustix", "windows-sys 0.48.0", ] @@ -2038,9 +2059,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jemalloc-sys" -version = "0.5.3+5.3.0-patched" +version = "0.5.4+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9bd5d616ea7ed58b571b2e209a65759664d7fb021a0819d7a790afc67e47ca1" +checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" dependencies = [ "cc", "libc", @@ -2165,6 +2186,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "libm" version = "0.1.4" @@ -2214,15 +2245,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] name = "litemap" @@ -2446,7 +2471,7 @@ dependencies = [ "lazy_static", "libc", "libffi", - "libloading", + "libloading 0.8.1", "log", "measureme", "rand", @@ -2454,7 +2479,7 @@ dependencies = [ "rustc_version", "serde", "smallvec", - "ui_test 0.11.7", + "ui_test 0.21.2", ] [[package]] @@ -2659,12 +2684,19 @@ dependencies = [ "serde", "serde_json", "sysinfo", + "tabled", "tar", "tempfile", "xz", "zip", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -2719,6 +2751,17 @@ dependencies = [ "unwind", ] +[[package]] +name = "papergrid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8" +dependencies = [ + "bytecount", + "fnv", + "unicode-width", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -2927,6 +2970,30 @@ dependencies = [ "pad", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -3006,6 +3073,27 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575fc2d9b3da54adbdfaddf6eca48fec256d977c8630a1750b8991347d1ac911" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "r-efi-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" +dependencies = [ + "compiler_builtins", + "r-efi", + "rustc-std-workspace-core", +] + [[package]] name = "rand" version = "0.8.5" @@ -3259,6 +3347,7 @@ dependencies = [ "rustc_driver", "rustc_driver_impl", "rustc_smir", + "stable_mir", ] [[package]] @@ -3927,7 +4016,7 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "libloading", + "libloading 0.7.4", "rustc-rayon", "rustc-rayon-core", "rustc_ast", @@ -4058,7 +4147,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "bitflags 1.3.2", - "libloading", + "libloading 0.7.4", "odht", "rustc_ast", "rustc_attr", @@ -4273,7 +4362,7 @@ dependencies = [ name = "rustc_plugin_impl" version = "0.0.0" dependencies = [ - "libloading", + "libloading 0.7.4", "rustc_ast", "rustc_errors", "rustc_fluent_macro", @@ -4314,7 +4403,6 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", - "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_serialize", @@ -4420,10 +4508,9 @@ dependencies = [ "rustc_hir", "rustc_interface", "rustc_middle", - "rustc_session", "rustc_span", "rustc_target", - "scoped-tls", + "stable_mir", "tracing", ] @@ -4476,6 +4563,7 @@ dependencies = [ "rustc_data_structures", "rustc_feature", "rustc_fs_util", + "rustc_index", "rustc_macros", "rustc_serialize", "rustc_span", @@ -4666,7 +4754,7 @@ dependencies = [ "annotate-snippets", "anyhow", "bytecount", - "cargo_metadata", + "cargo_metadata 0.15.4", "clap", "diff", "dirs", @@ -4690,28 +4778,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.22" +version = "0.38.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" +checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" -dependencies = [ - "bitflags 2.3.3", - "errno", - "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys 0.48.0", ] @@ -4974,6 +5048,14 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "stable_mir" +version = "0.1.0-preview" +dependencies = [ + "scoped-tls", + "tracing", +] + [[package]] name = "stacker" version = "0.1.15" @@ -4999,6 +5081,7 @@ version = "0.0.0" dependencies = [ "addr2line", "alloc", + "cc", "cfg-if", "compiler_builtins", "core", @@ -5012,6 +5095,8 @@ dependencies = [ "panic_abort", "panic_unwind", "profiler_builtins", + "r-efi", + "r-efi-alloc", "rand", "rand_xorshift", "rustc-demangle", @@ -5160,6 +5245,30 @@ dependencies = [ "test", ] +[[package]] +name = "tabled" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d38d39c754ae037a9bc3ca1580a985db7371cd14f1229172d1db9093feb6739" +dependencies = [ + "papergrid", + "tabled_derive", + "unicode-width", +] + +[[package]] +name = "tabled_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "tar" version = "0.4.38" @@ -5173,15 +5282,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.22", + "rustix", "windows-sys 0.48.0", ] @@ -5218,11 +5326,11 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.37.22", + "rustix", "windows-sys 0.48.0", ] @@ -5342,7 +5450,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "ignore", "lazy_static", "miropt-test-tools", @@ -5639,18 +5747,23 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "ui_test" -version = "0.11.7" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21899b59f53717dfad29e4f46e5b21a200a1b6888ab86532a07cfc8b48dd78c" +checksum = "bfd8fb9b15c8332cf51bfc2dc4830063b2446a9c9d732421b56f2478024a3971" dependencies = [ + "annotate-snippets", + "anyhow", "bstr", "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "color-eyre", "colored", + "comma", "crossbeam-channel", - "diff", + "indicatif", "lazy_static", + "levenshtein", + "prettydiff", "regex", "rustc_version", "rustfix", @@ -5661,15 +5774,15 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.20.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd8fb9b15c8332cf51bfc2dc4830063b2446a9c9d732421b56f2478024a3971" +checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d" dependencies = [ "annotate-snippets", "anyhow", "bstr", "cargo-platform", - "cargo_metadata", + "cargo_metadata 0.15.4", "color-eyre", "colored", "comma", @@ -6043,19 +6156,21 @@ dependencies = [ [[package]] name = "windows-bindgen" -version = "0.49.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6935fb09b84ee57929ae92518b475f5dfdfbeb87c5334756acc28ee8e202b60" +checksum = "bc1f16b778125675feee0d15d6dd9f6af0e3ac52b3233d63a10aa39230c1cd75" dependencies = [ + "proc-macro2", + "rayon", + "syn 2.0.29", "windows-metadata", - "windows-tokens", ] [[package]] name = "windows-metadata" -version = "0.49.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5bca94a32bf1e6a376522b6601275a3b611ee885ec0f1b6a05f17e8cfd3385" +checksum = "753135d996f9da437c0b31dbde3032489a61708361929bcc07d4fba0b161000e" [[package]] name = "windows-sys" @@ -6105,12 +6220,6 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] -[[package]] -name = "windows-tokens" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34c9a3b28cb41db7385546f7f9a8179348dffc89923dde66857b1ba5312f6b4" - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" diff --git a/README.md b/README.md index 8a6c559b0b312..f0c45f341d812 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ See [the rustc-dev-guide for more info][sysllvm]. #### 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 +invokes `x.py`). `./configure` is the recommended way to programmatically 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. diff --git a/RELEASES.md b/RELEASES.md index d390f2b7f5ea8..e261294a032fd 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,120 @@ +Version 1.73.0 (2023-10-05) +========================== + + + +Language +-------- + +- [Uplift `clippy::fn_null_check` lint as `useless_ptr_null_checks`.](https://github.com/rust-lang/rust/pull/111717/) +- [Make `noop_method_call` warn by default.](https://github.com/rust-lang/rust/pull/111916/) +- [Support interpolated block for `try` and `async` in macros.](https://github.com/rust-lang/rust/pull/112953/) +- [Make `unconditional_recursion` lint detect recursive drops.](https://github.com/rust-lang/rust/pull/113902/) +- [Future compatibility warning for some impls being incorrectly considered not overlapping.](https://github.com/rust-lang/rust/pull/114023/) +- [The `invalid_reference_casting` lint is now **deny-by-default** (instead of allow-by-default)](https://github.com/rust-lang/rust/pull/112431) + + + +Compiler +-------- + +- [Write version information in a `.comment` section like GCC/Clang.](https://github.com/rust-lang/rust/pull/97550/) +- [Add documentation on v0 symbol mangling.](https://github.com/rust-lang/rust/pull/97571/) +- [Stabilize `extern "thiscall"` and `"thiscall-unwind"` ABIs.](https://github.com/rust-lang/rust/pull/114562/) +- [Only check outlives goals on impl compared to trait.](https://github.com/rust-lang/rust/pull/109356/) +- [Infer type in irrefutable slice patterns with fixed length as array.](https://github.com/rust-lang/rust/pull/113199/) +- [Discard default auto trait impls if explicit ones exist.](https://github.com/rust-lang/rust/pull/113312/) +- Add several new tier 3 targets: + - [`aarch64-unknown-teeos`](https://github.com/rust-lang/rust/pull/113480/) + - [`csky-unknown-linux-gnuabiv2`](https://github.com/rust-lang/rust/pull/113658/) + - [`riscv64-linux-android`](https://github.com/rust-lang/rust/pull/112858/) + - [`riscv64gc-unknown-hermit`](https://github.com/rust-lang/rust/pull/114004/) + - [`x86_64-unikraft-linux-musl`](https://github.com/rust-lang/rust/pull/113411/) + - [`x86_64-unknown-linux-ohos`](https://github.com/rust-lang/rust/pull/113061/) +- [Add `wasm32-wasi-preview1-threads` as a tier 2 target.](https://github.com/rust-lang/rust/pull/112922/) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + +Libraries +--------- + +- [Add `Read`, `Write` and `Seek` impls for `Arc`.](https://github.com/rust-lang/rust/pull/94748/) +- [Merge functionality of `io::Sink` into `io::Empty`.](https://github.com/rust-lang/rust/pull/98154/) +- [Implement `RefUnwindSafe` for `Backtrace`](https://github.com/rust-lang/rust/pull/100455/) +- [Make `ExitStatus` implement `Default`](https://github.com/rust-lang/rust/pull/106425/) +- [`impl SliceIndex for (Bound, Bound)`](https://github.com/rust-lang/rust/pull/111081/) +- [Change default panic handler message format.](https://github.com/rust-lang/rust/pull/112849/) +- [Cleaner `assert_eq!` & `assert_ne!` panic messages.](https://github.com/rust-lang/rust/pull/111071/) +- [Correct the (deprecated) Android `stat` struct definitions.](https://github.com/rust-lang/rust/pull/113130/) + + + +Stabilized APIs +--------------- + +- [Unsigned `{integer}::div_ceil`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.div_ceil) +- [Unsigned `{integer}::next_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.next_multiple_of) +- [Unsigned `{integer}::checked_next_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.checked_next_multiple_of) +- [`std::ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/std/ffi/struct.FromBytesUntilNulError.html) +- [`std::os::unix::fs::chown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chown.html) +- [`std::os::unix::fs::fchown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.fchown.html) +- [`std::os::unix::fs::lchown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.lchown.html) +- [`LocalKey::>::get`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.get) +- [`LocalKey::>::set`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.set) +- [`LocalKey::>::take`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.take) +- [`LocalKey::>::replace`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.replace) +- [`LocalKey::>::with_borrow`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.with_borrow) +- [`LocalKey::>::with_borrow_mut`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.with_borrow_mut) +- [`LocalKey::>::set`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.set-1) +- [`LocalKey::>::take`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.take-1) +- [`LocalKey::>::replace`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.replace-1) + +These APIs are now stable in const contexts: + +- [`rc::Weak::new`](https://doc.rust-lang.org/stable/alloc/rc/struct.Weak.html#method.new) +- [`sync::Weak::new`](https://doc.rust-lang.org/stable/alloc/sync/struct.Weak.html#method.new) +- [`NonNull::as_ref`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.as_ref) + + + +Cargo +----- + +- [Encode URL params correctly for `SourceId` in `Cargo.lock`.](https://github.com/rust-lang/cargo/pull/12280/) +- [Bail out an error when using `cargo::` in custom build script.](https://github.com/rust-lang/cargo/pull/12332/) + + + +Misc +---- + + + +Compatibility Notes +------------------- + +- [Update the minimum external LLVM to 15.](https://github.com/rust-lang/rust/pull/114148/) +- [Check for non-defining uses of return position `impl Trait`.](https://github.com/rust-lang/rust/pull/112842/) + + + +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. + +- [Remove LLVM pointee types, supporting only opaque pointers.](https://github.com/rust-lang/rust/pull/105545/) +- [Port PGO/LTO/BOLT optimized build pipeline to Rust.](https://github.com/rust-lang/rust/pull/112235/) +- [Replace in-tree `rustc_apfloat` with the new version of the crate.](https://github.com/rust-lang/rust/pull/113843/) +- [Update to LLVM 17.](https://github.com/rust-lang/rust/pull/114048/) +- [Add `internal_features` lint for internal unstable features.](https://github.com/rust-lang/rust/pull/108955/) +- [Mention style for new syntax in tracking issue template.](https://github.com/rust-lang/rust/pull/113586/) + Version 1.72.1 (2023-09-19) =========================== diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 41003ad83f311..dcb165f9fdbf7 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -13,6 +13,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } # Make sure rustc_smir ends up in the sysroot, because this # crate is intended to be used by stable MIR consumers, which are not in-tree rustc_smir = { path = "../rustc_smir" } +stable_mir = { path = "../stable_mir" } [dependencies.jemalloc-sys] version = "0.5.0" diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml index 48b199cb8eed9..c43fd745e8f5b 100644 --- a/compiler/rustc_abi/Cargo.toml +++ b/compiler/rustc_abi/Cargo.toml @@ -15,7 +15,9 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } [features] default = ["nightly", "randomize"] -randomize = ["rand", "rand_xoshiro"] +randomize = ["rand", "rand_xoshiro", "nightly"] +# rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain +# without depending on rustc_data_structures, rustc_macros and rustc_serialize nightly = [ "rustc_data_structures", "rustc_index/nightly", diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 0706dc18f0ec6..00d862ca27b7b 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1,21 +1,27 @@ -use super::*; -use std::fmt::Write; +use std::fmt::{self, Write}; +use std::ops::Deref; use std::{borrow::Borrow, cmp, iter, ops::Bound}; -#[cfg(feature = "randomize")] -use rand::{seq::SliceRandom, SeedableRng}; -#[cfg(feature = "randomize")] -use rand_xoshiro::Xoshiro128StarStar; - +use rustc_index::Idx; use tracing::debug; +use crate::{ + Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche, + NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, + Variants, WrappingRange, +}; + pub trait LayoutCalculator { type TargetDataLayoutRef: Borrow; fn delay_bug(&self, txt: String); fn current_data_layout(&self) -> Self::TargetDataLayoutRef; - fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS { + fn scalar_pair( + &self, + a: Scalar, + b: Scalar, + ) -> LayoutS { let dl = self.current_data_layout(); let dl = dl.borrow(); let b_align = b.align(dl); @@ -31,7 +37,7 @@ pub trait LayoutCalculator { .max_by_key(|niche| niche.available(dl)); LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO, b_offset].into(), memory_index: [0, 1].into(), @@ -45,40 +51,45 @@ pub trait LayoutCalculator { } } - fn univariant( + fn univariant< + 'a, + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, + >( &self, dl: &TargetDataLayout, - fields: &IndexSlice>, + fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, - ) -> Option { + ) -> Option> { let layout = univariant(self, dl, fields, repr, kind, NicheBias::Start); - // Enums prefer niches close to the beginning or the end of the variants so that other (smaller) - // data-carrying variants can be packed into the space after/before the niche. + // Enums prefer niches close to the beginning or the end of the variants so that other + // (smaller) data-carrying variants can be packed into the space after/before the niche. // If the default field ordering does not give us a niche at the front then we do a second - // run and bias niches to the right and then check which one is closer to one of the struct's - // edges. + // run and bias niches to the right and then check which one is closer to one of the + // struct's edges. if let Some(layout) = &layout { // Don't try to calculate an end-biased layout for unsizable structs, // otherwise we could end up with different layouts for - // Foo and Foo which would break unsizing + // Foo and Foo which would break unsizing. if !matches!(kind, StructKind::MaybeUnsized) { if let Some(niche) = layout.largest_niche { let head_space = niche.offset.bytes(); - let niche_length = niche.value.size(dl).bytes(); - let tail_space = layout.size.bytes() - head_space - niche_length; + let niche_len = niche.value.size(dl).bytes(); + let tail_space = layout.size.bytes() - head_space - niche_len; - // This may end up doing redundant work if the niche is already in the last field - // (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get - // the unpadded size so we try anyway. + // This may end up doing redundant work if the niche is already in the last + // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial + // to get the unpadded size so we try anyway. if fields.len() > 1 && head_space != 0 && tail_space > 0 { let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End) .expect("alt layout should always work"); - let niche = alt_layout + let alt_niche = alt_layout .largest_niche .expect("alt layout should have a niche like the regular one"); - let alt_head_space = niche.offset.bytes(); - let alt_niche_len = niche.value.size(dl).bytes(); + let alt_head_space = alt_niche.offset.bytes(); + let alt_niche_len = alt_niche.value.size(dl).bytes(); let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len; @@ -93,7 +104,7 @@ pub trait LayoutCalculator { alt_layout: {}\n", layout.size.bytes(), head_space, - niche_length, + niche_len, tail_space, alt_head_space, alt_niche_len, @@ -114,11 +125,13 @@ pub trait LayoutCalculator { layout } - fn layout_of_never_type(&self) -> LayoutS { + fn layout_of_never_type( + &self, + ) -> LayoutS { let dl = self.current_data_layout(); let dl = dl.borrow(); LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Primitive, abi: Abi::Uninhabited, largest_niche: None, @@ -129,10 +142,15 @@ pub trait LayoutCalculator { } } - fn layout_of_struct_or_enum( + fn layout_of_struct_or_enum< + 'a, + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, + >( &self, repr: &ReprOptions, - variants: &IndexSlice>>, + variants: &IndexSlice>, is_enum: bool, is_unsafe_cell: bool, scalar_valid_range: (Bound, Bound), @@ -140,7 +158,7 @@ pub trait LayoutCalculator { discriminants: impl Iterator, dont_niche_optimize_enum: bool, always_sized: bool, - ) -> Option { + ) -> Option> { let dl = self.current_data_layout(); let dl = dl.borrow(); @@ -155,11 +173,11 @@ pub trait LayoutCalculator { // but *not* an encoding of the discriminant (e.g., a tag value). // See issue #49298 for more details on the need to leave space // for non-ZST uninhabited data (mostly partial initialization). - let absent = |fields: &IndexSlice>| { - let uninhabited = fields.iter().any(|f| f.abi().is_uninhabited()); + let absent = |fields: &IndexSlice| { + let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited()); // We cannot ignore alignment; that might lead us to entirely discard a variant and // produce an enum that is less aligned than it should be! - let is_1zst = fields.iter().all(|f| f.0.is_1zst()); + let is_1zst = fields.iter().all(|f| f.is_1zst()); uninhabited && is_1zst }; let (present_first, present_second) = { @@ -176,7 +194,7 @@ pub trait LayoutCalculator { } // If it's a struct, still compute a layout so that we can still compute the // field offsets. - None => FIRST_VARIANT, + None => VariantIdx::new(0), }; let is_struct = !is_enum || @@ -279,12 +297,12 @@ pub trait LayoutCalculator { // variant layouts, so we can't store them in the // overall LayoutS. Store the overall LayoutS // and the variant LayoutSs here until then. - struct TmpLayout { - layout: LayoutS, - variants: IndexVec, + struct TmpLayout { + layout: LayoutS, + variants: IndexVec>, } - let calculate_niche_filling_layout = || -> Option { + let calculate_niche_filling_layout = || -> Option> { if dont_niche_optimize_enum { return None; } @@ -322,13 +340,14 @@ pub trait LayoutCalculator { let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); - let count = niche_variants.size_hint().1.unwrap() as u128; + let count = + (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1; // Find the field with the largest niche let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index] .iter() .enumerate() - .filter_map(|(j, field)| Some((j, field.largest_niche()?))) + .filter_map(|(j, field)| Some((j, field.largest_niche?))) .max_by_key(|(_, niche)| niche.available(dl)) .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?; let niche_offset = @@ -443,7 +462,7 @@ pub trait LayoutCalculator { let discr_type = repr.discr_type(); let bits = Integer::from_attr(dl, discr_type).size().bits(); for (i, mut val) in discriminants { - if variants[i].iter().any(|f| f.abi().is_uninhabited()) { + if variants[i].iter().any(|f| f.abi.is_uninhabited()) { continue; } if discr_type.is_signed() { @@ -484,7 +503,7 @@ pub trait LayoutCalculator { if repr.c() { for fields in variants { for field in fields { - prefix_align = prefix_align.max(field.align().abi); + prefix_align = prefix_align.max(field.align.abi); } } } @@ -503,9 +522,9 @@ pub trait LayoutCalculator { // Find the first field we can't move later // to make room for a larger discriminant. for field_idx in st.fields.index_by_increasing_offset() { - let field = &field_layouts[FieldIdx::from_usize(field_idx)]; - if !field.0.is_1zst() { - start_align = start_align.min(field.align().abi); + let field = &field_layouts[FieldIdx::new(field_idx)]; + if !field.is_1zst() { + start_align = start_align.min(field.align.abi); break; } } @@ -587,7 +606,7 @@ pub trait LayoutCalculator { let tag_mask = ity.size().unsigned_int_max(); let tag = Scalar::Initialized { - value: Int(ity, signed), + value: Primitive::Int(ity, signed), valid_range: WrappingRange { start: (min as u128 & tag_mask), end: (max as u128 & tag_mask), @@ -612,7 +631,7 @@ pub trait LayoutCalculator { }; // We skip *all* ZST here and later check if we are good in terms of alignment. // This lets us handle some cases involving aligned ZST. - let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.0.is_zst()); + let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { (None, None) => { common_prim_initialized_in_all_variants = false; @@ -624,7 +643,7 @@ pub trait LayoutCalculator { break; } }; - let prim = match field.abi() { + let prim = match field.abi { Abi::Scalar(scalar) => { common_prim_initialized_in_all_variants &= matches!(scalar, Scalar::Initialized { .. }); @@ -655,7 +674,7 @@ pub trait LayoutCalculator { // Common prim might be uninit. Scalar::Union { value: prim } }; - let pair = self.scalar_pair(tag, prim_scalar); + let pair = self.scalar_pair::(tag, prim_scalar); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index.raw, [0, 1]); @@ -663,8 +682,8 @@ pub trait LayoutCalculator { } _ => panic!(), }; - if pair_offsets[FieldIdx::from_u32(0)] == Size::ZERO - && pair_offsets[FieldIdx::from_u32(1)] == *offset + if pair_offsets[FieldIdx::new(0)] == Size::ZERO + && pair_offsets[FieldIdx::new(1)] == *offset && align == pair.align && size == pair.size { @@ -684,7 +703,8 @@ pub trait LayoutCalculator { // Also do not overwrite any already existing "clever" ABIs. if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) { variant.abi = abi; - // Also need to bump up the size and alignment, so that the entire value fits in here. + // Also need to bump up the size and alignment, so that the entire value fits + // in here. variant.size = cmp::max(variant.size, size); variant.align.abi = cmp::max(variant.align.abi, align.abi); } @@ -720,8 +740,9 @@ pub trait LayoutCalculator { // pick the layout with the larger niche; otherwise, // pick tagged as it has simpler codegen. use cmp::Ordering::*; - let niche_size = - |tmp_l: &TmpLayout| tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)); + let niche_size = |tmp_l: &TmpLayout| { + tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) + }; match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) { (Greater, _) => nl, (Equal, Less) => nl, @@ -741,11 +762,16 @@ pub trait LayoutCalculator { Some(best_layout.layout) } - fn layout_of_union( + fn layout_of_union< + 'a, + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, + >( &self, repr: &ReprOptions, - variants: &IndexSlice>>, - ) -> Option { + variants: &IndexSlice>, + ) -> Option> { let dl = self.current_data_layout(); let dl = dl.borrow(); let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; @@ -762,24 +788,24 @@ pub trait LayoutCalculator { }; let mut size = Size::ZERO; - let only_variant = &variants[FIRST_VARIANT]; + let only_variant = &variants[VariantIdx::new(0)]; for field in only_variant { - if field.0.is_unsized() { + if field.is_unsized() { self.delay_bug("unsized field in union".to_string()); } - align = align.max(field.align()); - max_repr_align = max_repr_align.max(field.max_repr_align()); - size = cmp::max(size, field.size()); + align = align.max(field.align); + max_repr_align = max_repr_align.max(field.max_repr_align); + size = cmp::max(size, field.size); - if field.0.is_zst() { + if field.is_zst() { // Nothing more to do for ZST fields continue; } if let Ok(common) = common_non_zst_abi_and_align { // Discard valid range information and allow undef - let field_abi = field.abi().to_union(); + let field_abi = field.abi.to_union(); if let Some((common_abi, common_align)) = common { if common_abi != field_abi { @@ -790,15 +816,14 @@ pub trait LayoutCalculator { // have the same alignment if !matches!(common_abi, Abi::Aggregate { .. }) { assert_eq!( - common_align, - field.align().abi, + common_align, field.align.abi, "non-Aggregate field with matching ABI but differing alignment" ); } } } else { // First non-ZST field: record its ABI and alignment - common_non_zst_abi_and_align = Ok(Some((field_abi, field.align().abi))); + common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi))); } } } @@ -830,7 +855,7 @@ pub trait LayoutCalculator { }; Some(LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?), abi, largest_niche: None, @@ -848,14 +873,19 @@ enum NicheBias { End, } -fn univariant( +fn univariant< + 'a, + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, +>( this: &(impl LayoutCalculator + ?Sized), dl: &TargetDataLayout, - fields: &IndexSlice>, + fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, niche_bias: NicheBias, -) -> Option { +) -> Option> { let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; @@ -868,15 +898,18 @@ fn univariant( // If `-Z randomize-layout` was enabled for the type definition we can shuffle // the field ordering to try and catch some code making assumptions about layouts - // we don't guarantee + // we don't guarantee. if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { #[cfg(feature = "randomize")] { - // `ReprOptions.layout_seed` is a deterministic seed that we can use to - // randomize field ordering with - let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64()); - - // Shuffle the ordering of the fields + use rand::{seq::SliceRandom, SeedableRng}; + // `ReprOptions.layout_seed` is a deterministic seed we can use to randomize field + // ordering. + let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64( + repr.field_shuffle_seed.as_u64(), + ); + + // Shuffle the ordering of the fields. optimizing.shuffle(&mut rng); } // Otherwise we just leave things alone and actually optimize the type's fields @@ -884,35 +917,34 @@ fn univariant( // To allow unsizing `&Foo` -> `&Foo`, the layout of the struct must // not depend on the layout of the tail. let max_field_align = - fields_excluding_tail.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1); + fields_excluding_tail.iter().map(|f| f.align.abi.bytes()).max().unwrap_or(1); let largest_niche_size = fields_excluding_tail .iter() - .filter_map(|f| f.largest_niche()) + .filter_map(|f| f.largest_niche) .map(|n| n.available(dl)) .max() .unwrap_or(0); - // Calculates a sort key to group fields by their alignment or possibly some size-derived - // pseudo-alignment. - let alignment_group_key = |layout: Layout<'_>| { + // Calculates a sort key to group fields by their alignment or possibly some + // size-derived pseudo-alignment. + let alignment_group_key = |layout: &F| { if let Some(pack) = pack { - // return the packed alignment in bytes - layout.align().abi.min(pack).bytes() + // Return the packed alignment in bytes. + layout.align.abi.min(pack).bytes() } else { - // returns log2(effective-align). - // This is ok since `pack` applies to all fields equally. - // The calculation assumes that size is an integer multiple of align, except for ZSTs. - // - let align = layout.align().abi.bytes(); - let size = layout.size().bytes(); - let niche_size = layout.largest_niche().map(|n| n.available(dl)).unwrap_or(0); - // group [u8; 4] with align-4 or [u8; 6] with align-2 fields + // Returns `log2(effective-align)`. This is ok since `pack` applies to all + // fields equally. The calculation assumes that size is an integer multiple of + // align, except for ZSTs. + let align = layout.align.abi.bytes(); + let size = layout.size.bytes(); + let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0); + // Group [u8; 4] with align-4 or [u8; 6] with align-2 fields. let size_as_align = align.max(size).trailing_zeros(); let size_as_align = if largest_niche_size > 0 { match niche_bias { - // Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the array - // to the front in the first case (for aligned loads) but keep the bool in front - // in the second case for its niches. + // Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the + // array to the front in the first case (for aligned loads) but keep + // the bool in front in the second case for its niches. NicheBias::Start => max_field_align.trailing_zeros().min(size_as_align), // When moving niches towards the end of the struct then for // A((u8, u8, u8, bool), (u8, bool, u8)) we want to keep the first tuple @@ -931,18 +963,18 @@ fn univariant( match kind { StructKind::AlwaysSized | StructKind::MaybeUnsized => { - // Currently `LayoutS` only exposes a single niche so sorting is usually sufficient - // to get one niche into the preferred position. If it ever supported multiple niches - // then a more advanced pick-and-pack approach could provide better results. - // But even for the single-niche cache it's not optimal. E.g. for - // A(u32, (bool, u8), u16) it would be possible to move the bool to the front - // but it would require packing the tuple together with the u16 to build a 4-byte - // group so that the u32 can be placed after it without padding. This kind - // of packing can't be achieved by sorting. + // Currently `LayoutS` only exposes a single niche so sorting is usually + // sufficient to get one niche into the preferred position. If it ever + // supported multiple niches then a more advanced pick-and-pack approach could + // provide better results. But even for the single-niche cache it's not + // optimal. E.g. for A(u32, (bool, u8), u16) it would be possible to move the + // bool to the front but it would require packing the tuple together with the + // u16 to build a 4-byte group so that the u32 can be placed after it without + // padding. This kind of packing can't be achieved by sorting. optimizing.sort_by_key(|&x| { - let f = fields[x]; - let field_size = f.size().bytes(); - let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); + let f = &fields[x]; + let field_size = f.size.bytes(); + let niche_size = f.largest_niche.map_or(0, |n| n.available(dl)); let niche_size_key = match niche_bias { // large niche first NicheBias::Start => !niche_size, @@ -950,8 +982,8 @@ fn univariant( NicheBias::End => niche_size, }; let inner_niche_offset_key = match niche_bias { - NicheBias::Start => f.largest_niche().map_or(0, |n| n.offset.bytes()), - NicheBias::End => f.largest_niche().map_or(0, |n| { + NicheBias::Start => f.largest_niche.map_or(0, |n| n.offset.bytes()), + NicheBias::End => f.largest_niche.map_or(0, |n| { !(field_size - n.value.size(dl).bytes() - n.offset.bytes()) }), }; @@ -975,8 +1007,8 @@ fn univariant( // And put the largest niche in an alignment group at the end // so it can be used as discriminant in jagged enums optimizing.sort_by_key(|&x| { - let f = fields[x]; - let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); + let f = &fields[x]; + let niche_size = f.largest_niche.map_or(0, |n| n.available(dl)); (alignment_group_key(f), niche_size) }); } @@ -1012,24 +1044,24 @@ fn univariant( )); } - if field.0.is_unsized() { + if field.is_unsized() { sized = false; } // Invariant: offset < dl.obj_size_bound() <= 1<<61 let field_align = if let Some(pack) = pack { - field.align().min(AbiAndPrefAlign::new(pack)) + field.align.min(AbiAndPrefAlign::new(pack)) } else { - field.align() + field.align }; offset = offset.align_to(field_align.abi); align = align.max(field_align); - max_repr_align = max_repr_align.max(field.max_repr_align()); + max_repr_align = max_repr_align.max(field.max_repr_align); debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i] = offset; - if let Some(mut niche) = field.largest_niche() { + if let Some(mut niche) = field.largest_niche { let available = niche.available(dl); // Pick up larger niches. let prefer_new_niche = match niche_bias { @@ -1044,7 +1076,7 @@ fn univariant( } } - offset = offset.checked_add(field.size(), dl)?; + offset = offset.checked_add(field.size, dl)?; } // The unadjusted ABI alignment does not include repr(align), but does include repr(pack). @@ -1068,7 +1100,7 @@ fn univariant( inverse_memory_index.invert_bijective_mapping() } else { debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); - inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect() + inverse_memory_index.into_iter().map(|it| it.index() as u32).collect() }; let size = min_size.align_to(align.abi); let mut layout_of_single_non_zst_field = None; @@ -1077,7 +1109,7 @@ fn univariant( if sized && size.bytes() > 0 { // We skip *all* ZST here and later check if we are good in terms of alignment. // This lets us handle some cases involving aligned ZST. - let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst()); + let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.is_zst()); match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) { // We have exactly one non-ZST field. @@ -1085,18 +1117,17 @@ fn univariant( layout_of_single_non_zst_field = Some(field); // Field fills the struct and it has a scalar or scalar pair ABI. - if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size() - { - match field.abi() { + if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size { + match field.abi { // For plain scalars, or vectors of them, we can't unpack // newtypes for `#[repr(C)]`, as that affects C ABIs. Abi::Scalar(_) | Abi::Vector { .. } if optimize => { - abi = field.abi(); + abi = field.abi; } // But scalar pairs are Rust-specific and get // treated as aggregates by C ABIs anyway. Abi::ScalarPair(..) => { - abi = field.abi(); + abi = field.abi; } _ => {} } @@ -1105,7 +1136,7 @@ fn univariant( // Two non-ZST fields, and they're both scalars. (Some((i, a)), Some((j, b)), None) => { - match (a.abi(), b.abi()) { + match (a.abi, b.abi) { (Abi::Scalar(a), Abi::Scalar(b)) => { // Order by the memory placement, not source order. let ((i, a), (j, b)) = if offsets[i] < offsets[j] { @@ -1113,7 +1144,7 @@ fn univariant( } else { ((j, b), (i, a)) }; - let pair = this.scalar_pair(a, b); + let pair = this.scalar_pair::(a, b); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index.raw, [0, 1]); @@ -1121,8 +1152,8 @@ fn univariant( } _ => panic!(), }; - if offsets[i] == pair_offsets[FieldIdx::from_usize(0)] - && offsets[j] == pair_offsets[FieldIdx::from_usize(1)] + if offsets[i] == pair_offsets[FieldIdx::new(0)] + && offsets[j] == pair_offsets[FieldIdx::new(1)] && align == pair.align && size == pair.size { @@ -1138,13 +1169,13 @@ fn univariant( _ => {} } } - if fields.iter().any(|f| f.abi().is_uninhabited()) { + if fields.iter().any(|f| f.abi.is_uninhabited()) { abi = Abi::Uninhabited; } let unadjusted_abi_align = if repr.transparent() { match layout_of_single_non_zst_field { - Some(l) => l.unadjusted_abi_align(), + Some(l) => l.unadjusted_abi_align, None => { // `repr(transparent)` with all ZST fields. align.abi @@ -1155,7 +1186,7 @@ fn univariant( }; Some(LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets, memory_index }, abi, largest_niche, @@ -1166,17 +1197,22 @@ fn univariant( }) } -fn format_field_niches( - layout: &LayoutS, - fields: &IndexSlice>, +fn format_field_niches< + 'a, + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, +>( + layout: &LayoutS, + fields: &IndexSlice, dl: &TargetDataLayout, ) -> String { let mut s = String::new(); for i in layout.fields.index_by_increasing_offset() { let offset = layout.fields.offset(i); - let f = fields[i.into()]; - write!(s, "[o{}a{}s{}", offset.bytes(), f.align().abi.bytes(), f.size().bytes()).unwrap(); - if let Some(n) = f.largest_niche() { + let f = &fields[FieldIdx::new(i)]; + write!(s, "[o{}a{}s{}", offset.bytes(), f.align.abi.bytes(), f.size.bytes()).unwrap(); + if let Some(n) = f.largest_niche { write!( s, " n{}b{}s{}", diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b30ff058a3092..45b3e76cca69a 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,23 +1,22 @@ -#![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))] +#![cfg_attr(feature = "nightly", feature(step_trait))] #![cfg_attr(feature = "nightly", allow(internal_features))] use std::fmt; -#[cfg(feature = "nightly")] -use std::iter::Step; use std::num::{NonZeroUsize, ParseIntError}; use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub}; use std::str::FromStr; use bitflags::bitflags; -use rustc_data_structures::intern::Interned; -use rustc_data_structures::stable_hasher::Hash64; +use rustc_index::{Idx, IndexSlice, IndexVec}; + #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::StableOrd; -use rustc_index::{IndexSlice, IndexVec}; #[cfg(feature = "nightly")] use rustc_macros::HashStable_Generic; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable}; +#[cfg(feature = "nightly")] +use std::iter::Step; mod layout; @@ -28,9 +27,6 @@ pub use layout::LayoutCalculator; /// instead of implementing everything in `rustc_middle`. pub trait HashStableContext {} -use Integer::*; -use Primitive::*; - bitflags! { #[derive(Default)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] @@ -53,10 +49,11 @@ bitflags! { #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum IntegerType { - /// Pointer sized integer type, i.e. isize and usize. The field shows signedness, that - /// is, `Pointer(true)` is isize. + /// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g. + /// `Pointer(true)` means `isize`. Pointer(bool), - /// Fix sized integer type, e.g. i8, u32, i128 The bool field shows signedness, `Fixed(I8, false)` means `u8` + /// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`. The bool field shows signedness, e.g. + /// `Fixed(I8, false)` means `u8`. Fixed(Integer, bool), } @@ -69,7 +66,7 @@ impl IntegerType { } } -/// Represents the repr options provided by the user, +/// Represents the repr options provided by the user. #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub struct ReprOptions { @@ -77,6 +74,7 @@ pub struct ReprOptions { pub align: Option, pub pack: Option, pub flags: ReprFlags, + #[cfg(feature = "randomize")] /// The seed to be used for randomizing a type's layout /// /// Note: This could technically be a `Hash128` which would @@ -84,7 +82,7 @@ pub struct ReprOptions { /// hash without loss, but it does pay the price of being larger. /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: Hash64, + pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64, } impl ReprOptions { @@ -139,7 +137,7 @@ impl ReprOptions { } /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` - /// was enabled for its declaration crate + /// was enabled for its declaration crate. pub fn can_randomize_type_layout(&self) -> bool { !self.inhibit_struct_field_reordering_opt() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) @@ -217,7 +215,8 @@ pub enum TargetDataLayoutErrors<'a> { } impl TargetDataLayout { - /// Parse data layout from an [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout) + /// Parse data layout from an + /// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout) /// /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be /// determined from llvm string. @@ -242,10 +241,11 @@ impl TargetDataLayout { }; // Parse a size string. - let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); + let parse_size = + |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); // Parse an alignment string. - let align = |s: &[&'a str], cause: &'a str| { + let parse_align = |s: &[&'a str], cause: &'a str| { if s.is_empty() { return Err(TargetDataLayoutErrors::MissingAlignment { cause }); } @@ -269,22 +269,22 @@ impl TargetDataLayout { [p] if p.starts_with('P') => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, - ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?, - ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?, + ["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?, + ["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?, + ["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?, // FIXME(erikdesjardins): we should be parsing nonzero address spaces // this will require replacing TargetDataLayout::{pointer_size,pointer_align} // with e.g. `fn pointer_size_in(AddressSpace)` [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { - dl.pointer_size = size(s, p)?; - dl.pointer_align = align(a, p)?; + dl.pointer_size = parse_size(s, p)?; + dl.pointer_align = parse_align(a, p)?; } [s, ref a @ ..] if s.starts_with('i') => { let Ok(bits) = s[1..].parse::() else { - size(&s[1..], "i")?; // For the user error. + parse_size(&s[1..], "i")?; // For the user error. continue; }; - let a = align(a, s)?; + let a = parse_align(a, s)?; match bits { 1 => dl.i1_align = a, 8 => dl.i8_align = a, @@ -301,8 +301,8 @@ impl TargetDataLayout { } } [s, ref a @ ..] if s.starts_with('v') => { - let v_size = size(&s[1..], "v")?; - let a = align(a, s)?; + let v_size = parse_size(&s[1..], "v")?; + let a = parse_align(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { v.1 = a; continue; @@ -339,6 +339,7 @@ impl TargetDataLayout { #[inline] pub fn ptr_sized_integer(&self) -> Integer { + use Integer::*; match self.pointer_size.bits() { 16 => I16, 32 => I32, @@ -747,7 +748,6 @@ impl Align { /// A pair of alignments, ABI-mandated and preferred. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] - pub struct AbiAndPrefAlign { pub abi: Align, pub pref: Align, @@ -773,7 +773,6 @@ impl AbiAndPrefAlign { /// Integers, also used for enum discriminants. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] - pub enum Integer { I8, I16, @@ -785,6 +784,7 @@ pub enum Integer { impl Integer { #[inline] pub fn size(self) -> Size { + use Integer::*; match self { I8 => Size::from_bytes(1), I16 => Size::from_bytes(2), @@ -805,6 +805,7 @@ impl Integer { } pub fn align(self, cx: &C) -> AbiAndPrefAlign { + use Integer::*; let dl = cx.data_layout(); match self { @@ -819,6 +820,7 @@ impl Integer { /// Returns the largest signed value that can be represented by this Integer. #[inline] pub fn signed_max(self) -> i128 { + use Integer::*; match self { I8 => i8::MAX as i128, I16 => i16::MAX as i128, @@ -831,6 +833,7 @@ impl Integer { /// Finds the smallest Integer type which can represent the signed value. #[inline] pub fn fit_signed(x: i128) -> Integer { + use Integer::*; match x { -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8, -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16, @@ -843,6 +846,7 @@ impl Integer { /// Finds the smallest Integer type which can represent the unsigned value. #[inline] pub fn fit_unsigned(x: u128) -> Integer { + use Integer::*; match x { 0..=0x0000_0000_0000_00ff => I8, 0..=0x0000_0000_0000_ffff => I16, @@ -854,6 +858,7 @@ impl Integer { /// Finds the smallest integer with the given alignment. pub fn for_align(cx: &C, wanted: Align) -> Option { + use Integer::*; let dl = cx.data_layout(); [I8, I16, I32, I64, I128].into_iter().find(|&candidate| { @@ -863,6 +868,7 @@ impl Integer { /// Find the largest integer with the given alignment or less. pub fn approximate_align(cx: &C, wanted: Align) -> Integer { + use Integer::*; let dl = cx.data_layout(); // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. @@ -908,6 +914,7 @@ pub enum Primitive { impl Primitive { pub fn size(self, cx: &C) -> Size { + use Primitive::*; let dl = cx.data_layout(); match self { @@ -922,6 +929,7 @@ impl Primitive { } pub fn align(self, cx: &C) -> AbiAndPrefAlign { + use Primitive::*; let dl = cx.data_layout(); match self { @@ -937,8 +945,7 @@ impl Primitive { } /// Inclusive wrap-around range of valid values, that is, if -/// start > end, it represents `start..=MAX`, -/// followed by `0..=end`. +/// start > end, it represents `start..=MAX`, followed by `0..=end`. /// /// That is, for an i8 primitive, a range of `254..=2` means following /// sequence: @@ -970,21 +977,21 @@ impl WrappingRange { /// Returns `self` with replaced `start` #[inline(always)] - pub fn with_start(mut self, start: u128) -> Self { + fn with_start(mut self, start: u128) -> Self { self.start = start; self } /// Returns `self` with replaced `end` #[inline(always)] - pub fn with_end(mut self, end: u128) -> Self { + fn with_end(mut self, end: u128) -> Self { self.end = end; self } /// Returns `true` if `size` completely fills the range. #[inline] - pub fn is_full_for(&self, size: Size) -> bool { + fn is_full_for(&self, size: Size) -> bool { let max_value = size.unsigned_int_max(); debug_assert!(self.start <= max_value && self.end <= max_value); self.start == (self.end.wrapping_add(1) & max_value) @@ -1027,10 +1034,11 @@ pub enum Scalar { impl Scalar { #[inline] pub fn is_bool(&self) -> bool { + use Integer::*; matches!( self, Scalar::Initialized { - value: Int(I8, false), + value: Primitive::Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } } ) @@ -1066,7 +1074,8 @@ impl Scalar { } #[inline] - /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union. + /// Allows the caller to mutate the valid range. This operation will panic if attempted on a + /// union. pub fn valid_range_mut(&mut self) -> &mut WrappingRange { match self { Scalar::Initialized { valid_range, .. } => valid_range, @@ -1074,7 +1083,8 @@ impl Scalar { } } - /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout + /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole + /// layout. #[inline] pub fn is_always_valid(&self, cx: &C) -> bool { match *self { @@ -1093,36 +1103,11 @@ impl Scalar { } } -rustc_index::newtype_index! { - /// The *source-order* index of a field in a variant. - /// - /// This is how most code after type checking refers to fields, rather than - /// using names (as names have hygiene complications and more complex lookup). - /// - /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order. - /// (It is for `repr(C)` `struct`s, however.) - /// - /// For example, in the following types, - /// ```rust - /// # enum Never {} - /// # #[repr(u16)] - /// enum Demo1 { - /// Variant0 { a: Never, b: i32 } = 100, - /// Variant1 { c: u8, d: u64 } = 10, - /// } - /// struct Demo2 { e: u8, f: u16, g: u8 } - /// ``` - /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, - /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and - /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. - #[derive(HashStable_Generic)] - pub struct FieldIdx {} -} - +// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. /// Describes how the fields of a type are located in memory. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] -pub enum FieldsShape { +pub enum FieldsShape { /// Scalar primitives and `!`, which never have fields. Primitive, @@ -1162,7 +1147,7 @@ pub enum FieldsShape { }, } -impl FieldsShape { +impl FieldsShape { #[inline] pub fn count(&self) -> usize { match *self { @@ -1188,7 +1173,7 @@ impl FieldsShape { assert!(i < count, "tried to access field {i} of array with {count} fields"); stride * i } - FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)], + FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::new(i)], } } @@ -1200,7 +1185,7 @@ impl FieldsShape { } FieldsShape::Union(_) | FieldsShape::Array { .. } => i, FieldsShape::Arbitrary { ref memory_index, .. } => { - memory_index[FieldIdx::from_usize(i)].try_into().unwrap() + memory_index[FieldIdx::new(i)].try_into().unwrap() } } } @@ -1216,7 +1201,7 @@ impl FieldsShape { if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { if use_small { for (field_idx, &mem_idx) in memory_index.iter_enumerated() { - inverse_small[mem_idx as usize] = field_idx.as_u32() as u8; + inverse_small[mem_idx as usize] = field_idx.index() as u8; } } else { inverse_big = memory_index.invert_bijective_mapping(); @@ -1229,7 +1214,7 @@ impl FieldsShape { if use_small { inverse_small[i] as usize } else { - inverse_big[i as u32].as_usize() + inverse_big[i as u32].index() } } }) @@ -1252,7 +1237,6 @@ impl AddressSpace { /// in terms of categories of C types there are ABI rules for. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] - pub enum Abi { Uninhabited, Scalar(Scalar), @@ -1373,9 +1357,10 @@ impl Abi { } } +// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] -pub enum Variants { +pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { index: VariantIdx }, @@ -1387,15 +1372,16 @@ pub enum Variants { /// For enums, the tag is the sole field of the layout. Multiple { tag: Scalar, - tag_encoding: TagEncoding, + tag_encoding: TagEncoding, tag_field: usize, - variants: IndexVec, + variants: IndexVec>, }, } +// NOTE: This struct is generic over the VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] -pub enum TagEncoding { +pub enum TagEncoding { /// The tag directly stores the discriminant, but possibly with a smaller layout /// (so converting the tag to the discriminant can require sign extension). Direct, @@ -1457,17 +1443,19 @@ impl Niche { return None; } - // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound. - // Given an eventual `Option`, we try to maximize the chance for `None` to occupy the niche of zero. - // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero. - // Having `None` in niche zero can enable some special optimizations. + // Extend the range of valid values being reserved by moving either `v.start` or `v.end` + // bound. Given an eventual `Option`, we try to maximize the chance for `None` to occupy + // the niche of zero. This is accomplished by preferring enums with 2 variants(`count==1`) + // and always taking the shortest path to niche zero. Having `None` in niche zero can + // enable some special optimizations. // // Bound selection criteria: // 1. Select closest to zero given wrapping semantics. // 2. Avoid moving past zero if possible. // - // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly. - // If niche zero is already reserved, the selection of bounds are of little interest. + // In practice this means that enums with `count > 1` are unlikely to claim niche zero, + // since they have to fit perfectly. If niche zero is already reserved, the selection of + // bounds are of little interest. let move_start = |v: WrappingRange| { let start = v.start.wrapping_sub(count) & max_value; Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) })) @@ -1501,29 +1489,12 @@ impl Niche { } } -rustc_index::newtype_index! { - /// The *source-order* index of a variant in a type. - /// - /// For enums, these are always `0..variant_count`, regardless of any - /// custom discriminants that may have been defined, and including any - /// variants that may end up uninhabited due to field types. (Some of the - /// variants may not be present in a monomorphized ABI [`Variants`], but - /// those skipped variants are always counted when determining the *index*.) - /// - /// `struct`s, `tuples`, and `unions`s are considered to have a single variant - /// with variant index zero, aka [`FIRST_VARIANT`]. - #[derive(HashStable_Generic)] - pub struct VariantIdx { - /// Equivalent to `VariantIdx(0)`. - const FIRST_VARIANT = 0; - } -} - +// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] -pub struct LayoutS { +pub struct LayoutS { /// Says where the fields are located within the layout. - pub fields: FieldsShape, + pub fields: FieldsShape, /// Encodes information about multi-variant layouts. /// Even with `Multiple` variants, a layout still has its own fields! Those are then @@ -1532,7 +1503,7 @@ pub struct LayoutS { /// /// To access all fields of this layout, both `fields` and the fields of the active variant /// must be taken into account. - pub variants: Variants, + pub variants: Variants, /// The `abi` defines how this data is passed between functions, and it defines /// value restrictions via `valid_range`. @@ -1561,13 +1532,13 @@ pub struct LayoutS { pub unadjusted_abi_align: Align, } -impl LayoutS { +impl LayoutS { pub fn scalar(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); let size = scalar.size(cx); let align = scalar.align(cx); LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Primitive, abi: Abi::Scalar(scalar), largest_niche, @@ -1579,7 +1550,11 @@ impl LayoutS { } } -impl fmt::Debug for LayoutS { +impl fmt::Debug for LayoutS +where + FieldsShape: fmt::Debug, + Variants: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // This is how `Layout` used to print before it become // `Interned`. We print it like this to avoid having to update @@ -1607,61 +1582,6 @@ impl fmt::Debug for LayoutS { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] -#[rustc_pass_by_value] -pub struct Layout<'a>(pub Interned<'a, LayoutS>); - -impl<'a> fmt::Debug for Layout<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // See comment on `::fmt` above. - self.0.0.fmt(f) - } -} - -impl<'a> Layout<'a> { - pub fn fields(self) -> &'a FieldsShape { - &self.0.0.fields - } - - pub fn variants(self) -> &'a Variants { - &self.0.0.variants - } - - pub fn abi(self) -> Abi { - self.0.0.abi - } - - pub fn largest_niche(self) -> Option { - self.0.0.largest_niche - } - - pub fn align(self) -> AbiAndPrefAlign { - self.0.0.align - } - - pub fn size(self) -> Size { - self.0.0.size - } - - pub fn max_repr_align(self) -> Option { - self.0.0.max_repr_align - } - - pub fn unadjusted_abi_align(self) -> Align { - self.0.0.unadjusted_abi_align - } - - /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. - /// - /// Currently, that means that the type is pointer-sized, pointer-aligned, - /// and has a scalar ABI. - pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { - self.size() == data_layout.pointer_size - && self.align().abi == data_layout.pointer_align.abi - && matches!(self.abi(), Abi::Scalar(..)) - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PointerKind { /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`. @@ -1681,7 +1601,7 @@ pub struct PointeeInfo { pub safe: Option, } -impl LayoutS { +impl LayoutS { /// Returns `true` if the layout corresponds to an unsized type. #[inline] pub fn is_unsized(&self) -> bool { diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f14463fe94029..bf8a7eb293e0d 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -15,7 +15,6 @@ #![feature(dropck_eyepatch)] #![feature(new_uninit)] #![feature(maybe_uninit_slice)] -#![feature(min_specialization)] #![feature(decl_macro)] #![feature(pointer_byte_offsets)] #![feature(rustc_attrs)] @@ -37,29 +36,13 @@ use std::ptr::{self, NonNull}; use std::slice; use std::{cmp, intrinsics}; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -fn cold_path R, R>(f: F) -> R { +fn outline R, R>(f: F) -> R { f() } -/// An arena that can hold objects of only one type. -pub struct TypedArena { - /// A pointer to the next object to be allocated. - ptr: Cell<*mut T>, - - /// A pointer to the end of the allocated area. When this pointer is - /// reached, a new chunk is allocated. - end: Cell<*mut T>, - - /// A vector of arena chunks. - chunks: RefCell>>, - - /// Marker indicating that dropping the arena causes its owned - /// instances of `T` to be dropped. - _own: PhantomData, -} - struct ArenaChunk { /// The raw storage for the arena chunk. storage: NonNull<[MaybeUninit]>, @@ -129,6 +112,23 @@ impl ArenaChunk { const PAGE: usize = 4096; const HUGE_PAGE: usize = 2 * 1024 * 1024; +/// An arena that can hold objects of only one type. +pub struct TypedArena { + /// A pointer to the next object to be allocated. + ptr: Cell<*mut T>, + + /// A pointer to the end of the allocated area. When this pointer is + /// reached, a new chunk is allocated. + end: Cell<*mut T>, + + /// A vector of arena chunks. + chunks: RefCell>>, + + /// Marker indicating that dropping the arena causes its owned + /// instances of `T` to be dropped. + _own: PhantomData, +} + impl Default for TypedArena { /// Creates a new `TypedArena`. fn default() -> TypedArena { @@ -143,77 +143,6 @@ impl Default for TypedArena { } } -trait IterExt { - fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T]; -} - -impl IterExt for I -where - I: IntoIterator, -{ - // This default collects into a `SmallVec` and then allocates by copying - // from it. The specializations below for types like `Vec` are more - // efficient, copying directly without the intermediate collecting step. - // This default could be made more efficient, like - // `DroplessArena::alloc_from_iter`, but it's not hot enough to bother. - #[inline] - default fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T] { - let vec: SmallVec<[_; 8]> = self.into_iter().collect(); - vec.alloc_from_iter(arena) - } -} - -impl IterExt for std::array::IntoIter { - #[inline] - fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - unsafe { - let start_ptr = arena.alloc_raw_slice(len); - self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len); - mem::forget(self); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - -impl IterExt for Vec { - #[inline] - fn alloc_from_iter(mut self, arena: &TypedArena) -> &mut [T] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - unsafe { - let start_ptr = arena.alloc_raw_slice(len); - self.as_ptr().copy_to_nonoverlapping(start_ptr, len); - self.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - -impl IterExt for SmallVec { - #[inline] - fn alloc_from_iter(mut self, arena: &TypedArena) -> &mut [A::Item] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - unsafe { - let start_ptr = arena.alloc_raw_slice(len); - self.as_ptr().copy_to_nonoverlapping(start_ptr, len); - self.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - impl TypedArena { /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] @@ -249,33 +178,55 @@ impl TypedArena { available_bytes >= additional_bytes } - /// Ensures there's enough space in the current chunk to fit `len` objects. #[inline] - fn ensure_capacity(&self, additional: usize) { - if !self.can_allocate(additional) { - self.grow(additional); - debug_assert!(self.can_allocate(additional)); - } - } - - #[inline] - unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T { + fn alloc_raw_slice(&self, len: usize) -> *mut T { assert!(mem::size_of::() != 0); assert!(len != 0); - self.ensure_capacity(len); + // Ensure the current chunk can fit `len` objects. + if !self.can_allocate(len) { + self.grow(len); + debug_assert!(self.can_allocate(len)); + } let start_ptr = self.ptr.get(); - // SAFETY: `self.ensure_capacity` makes sure that there is enough space - // for `len` elements. + // SAFETY: `can_allocate`/`grow` ensures that there is enough space for + // `len` elements. unsafe { self.ptr.set(start_ptr.add(len)) }; start_ptr } #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { + // This implementation is entirely separate to + // `DroplessIterator::alloc_from_iter`, even though conceptually they + // are the same. + // + // `DroplessIterator` (in the fast case) writes elements from the + // iterator one at a time into the allocated memory. That's easy + // because the elements don't implement `Drop`. But for `TypedArena` + // they do implement `Drop`, which means that if the iterator panics we + // could end up with some allocated-but-uninitialized elements, which + // will then cause UB in `TypedArena::drop`. + // + // Instead we use an approach where any iterator panic will occur + // before the memory is allocated. This function is much less hot than + // `DroplessArena::alloc_from_iter`, so it doesn't need to be + // hyper-optimized. assert!(mem::size_of::() != 0); - iter.alloc_from_iter(self) + + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + if vec.is_empty() { + return &mut []; + } + // Move the content to the arena by copying and then forgetting it. + let len = vec.len(); + let start_ptr = self.alloc_raw_slice(len); + unsafe { + vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + vec.set_len(0); + slice::from_raw_parts_mut(start_ptr, len) + } } /// Grows the arena. @@ -406,6 +357,8 @@ impl Default for DroplessArena { #[inline] fn default() -> DroplessArena { DroplessArena { + // We set both `start` and `end` to 0 so that the first call to + // alloc() will trigger a grow(). start: Cell::new(ptr::null_mut()), end: Cell::new(ptr::null_mut()), chunks: Default::default(), @@ -414,9 +367,11 @@ impl Default for DroplessArena { } impl DroplessArena { + #[inline(never)] + #[cold] fn grow(&self, layout: Layout) { // Add some padding so we can align `self.end` while - // stilling fitting in a `layout` allocation. + // still fitting in a `layout` allocation. let additional = layout.size() + cmp::max(DROPLESS_ALIGNMENT, layout.align()) - 1; unsafe { @@ -440,7 +395,7 @@ impl DroplessArena { let mut chunk = ArenaChunk::new(align_up(new_cap, PAGE)); self.start.set(chunk.start()); - // Align the end to DROPLESS_ALIGNMENT + // Align the end to DROPLESS_ALIGNMENT. let end = align_down(chunk.end().addr(), DROPLESS_ALIGNMENT); // Make sure we don't go past `start`. This should not happen since the allocation @@ -453,55 +408,40 @@ impl DroplessArena { } } - #[inline(never)] - #[cold] - fn grow_and_alloc_raw(&self, layout: Layout) -> *mut u8 { - self.grow(layout); - self.alloc_raw_without_grow(layout).unwrap() - } - - #[inline(never)] - #[cold] - fn grow_and_alloc(&self) -> *mut u8 { - self.grow_and_alloc_raw(Layout::new::()) - } - - /// Allocates a byte slice with specified layout from the current memory - /// chunk. Returns `None` if there is no free space left to satisfy the - /// request. - #[inline] - fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> { - let start = self.start.get().addr(); - let old_end = self.end.get(); - let end = old_end.addr(); - - // Align allocated bytes so that `self.end` stays aligned to DROPLESS_ALIGNMENT - let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT); - - // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT - unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) }; - - let new_end = align_down(end.checked_sub(bytes)?, layout.align()); - if start <= new_end { - let new_end = old_end.with_addr(new_end); - // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down` preserves alignment - // as both `end` and `bytes` are already aligned to DROPLESS_ALIGNMENT. - self.end.set(new_end); - Some(new_end) - } else { - None - } - } - #[inline] pub fn alloc_raw(&self, layout: Layout) -> *mut u8 { assert!(layout.size() != 0); - if let Some(a) = self.alloc_raw_without_grow(layout) { - return a; + + // This loop executes once or twice: if allocation fails the first + // time, the `grow` ensures it will succeed the second time. + loop { + let start = self.start.get().addr(); + let old_end = self.end.get(); + let end = old_end.addr(); + + // Align allocated bytes so that `self.end` stays aligned to + // DROPLESS_ALIGNMENT. + let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT); + + // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT. + unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) }; + + if let Some(sub) = end.checked_sub(bytes) { + let new_end = align_down(sub, layout.align()); + if start <= new_end { + let new_end = old_end.with_addr(new_end); + // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down` + // preserves alignment as both `end` and `bytes` are already + // aligned to DROPLESS_ALIGNMENT. + self.end.set(new_end); + return new_end; + } + } + + // No free space left. Allocate a new chunk to satisfy the request. + // On failure the grow will panic or abort. + self.grow(layout); } - // No free space left. Allocate a new chunk to satisfy the request. - // On failure the grow will panic or abort. - self.grow_and_alloc_raw(layout) } #[inline] @@ -509,13 +449,7 @@ impl DroplessArena { assert!(!mem::needs_drop::()); assert!(mem::size_of::() != 0); - let mem = if let Some(a) = self.alloc_raw_without_grow(Layout::for_value::(&object)) { - a - } else { - // No free space left. Allocate a new chunk to satisfy the request. - // On failure the grow will panic or abort. - self.grow_and_alloc::() - } as *mut T; + let mem = self.alloc_raw(Layout::new::()) as *mut T; unsafe { // Write into uninitialized memory. @@ -600,7 +534,7 @@ impl DroplessArena { unsafe { self.write_from_iter(iter, len, mem) } } (_, _) => { - cold_path(move || -> &mut [T] { + outline(move || -> &mut [T] { let mut vec: SmallVec<[_; 8]> = iter.collect(); if vec.is_empty() { return &mut []; @@ -712,10 +646,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { } #[allow(clippy::mut_from_ref)] - pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>( - &'a self, + pub fn alloc_from_iter, C>( + &self, iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [T] { + ) -> &mut [T] { T::allocate_from_iter(self, iter) } } diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index 3370146193a52..2dd5e96e513a3 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -1,3 +1,7 @@ +use crate::{attr, Attribute}; +use rustc_span::symbol::sym; +use rustc_span::Symbol; + #[derive(Debug)] pub enum EntryPointType { None, @@ -6,3 +10,26 @@ pub enum EntryPointType { Start, OtherMain, // Not an entry point, but some other function named main } + +pub fn entry_point_type( + attrs: &[Attribute], + at_root: bool, + name: Option, +) -> EntryPointType { + if attr::contains_name(attrs, sym::start) { + EntryPointType::Start + } else if attr::contains_name(attrs, sym::rustc_main) { + EntryPointType::RustcMainAttr + } else { + if let Some(name) = name && name == sym::main { + if at_root { + // This is a top-level function so it can be `main`. + EntryPointType::MainNamed + } else { + EntryPointType::OtherMain + } + } else { + EntryPointType::None + } + } +} diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 300b1486f9ba0..09bfbd02198c0 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -446,7 +446,7 @@ impl Token { } } - /// Returns `true` if the token can appear at the start of an pattern. + /// Returns `true` if the token can appear at the start of a pattern. /// /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now. pub fn can_begin_pattern(&self) -> bool { diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 8115c4b55b0af..aaeef1ff77d3d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -99,7 +99,7 @@ ast_lowering_misplaced_double_dot = .note = only allowed in tuple, tuple struct, and slice patterns ast_lowering_misplaced_impl_trait = - `impl Trait` only allowed in function and inherent method return types, not in {$position} + `impl Trait` only allowed in function and inherent method argument and return types, not in {$position} ast_lowering_misplaced_relax_trait_bound = `?Trait` bounds are only permitted at the point where a type parameter is declared diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index afcf8b15cd800..45a9bebfcf627 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -410,15 +410,11 @@ fn expand_format_args<'hir>( let format_options = use_format_options.then(|| { // Generate: // &[format_spec_0, format_spec_1, format_spec_2] - let elements: Vec<_> = fmt - .template - .iter() - .filter_map(|piece| { - let FormatArgsPiece::Placeholder(placeholder) = piece else { return None }; - Some(make_format_spec(ctx, macsp, placeholder, &mut argmap)) - }) - .collect(); - ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + let elements = ctx.arena.alloc_from_iter(fmt.template.iter().filter_map(|piece| { + let FormatArgsPiece::Placeholder(placeholder) = piece else { return None }; + Some(make_format_spec(ctx, macsp, placeholder, &mut argmap)) + })); + ctx.expr_array_ref(macsp, elements) }); let arguments = fmt.arguments.all_args(); @@ -477,10 +473,8 @@ fn expand_format_args<'hir>( // ::new_debug(&arg2), // … // ] - let elements: Vec<_> = arguments - .iter() - .zip(argmap) - .map(|(arg, ((_, ty), placeholder_span))| { + let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map( + |(arg, ((_, ty), placeholder_span))| { let placeholder_span = placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt()); let arg_span = match arg.kind { @@ -493,9 +487,9 @@ fn expand_format_args<'hir>( hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg), )); make_argument(ctx, placeholder_span, ref_arg, ty) - }) - .collect(); - ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + }, + )); + ctx.expr_array_ref(macsp, elements) } else { // Generate: // &match (&arg0, &arg1, &…) { @@ -528,19 +522,14 @@ fn expand_format_args<'hir>( make_argument(ctx, placeholder_span, arg, ty) }, )); - let elements: Vec<_> = arguments - .iter() - .map(|arg| { - let arg_expr = ctx.lower_expr(&arg.expr); - ctx.expr( - arg.expr.span.with_ctxt(macsp.ctxt()), - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr), - ) - }) - .collect(); - let args_tuple = ctx - .arena - .alloc(ctx.expr(macsp, hir::ExprKind::Tup(ctx.arena.alloc_from_iter(elements)))); + let elements = ctx.arena.alloc_from_iter(arguments.iter().map(|arg| { + let arg_expr = ctx.lower_expr(&arg.expr); + ctx.expr( + arg.expr.span.with_ctxt(macsp.ctxt()), + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr), + ) + })); + let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements))); let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args))); let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]); let match_expr = ctx.arena.alloc(ctx.expr_match( diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a59c83de0f46f..edc1e2f0b84d9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1308,7 +1308,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { match a { - Async::Yes { .. } => hir::IsAsync::Async, + Async::Yes { span, .. } => hir::IsAsync::Async(span), Async::No => hir::IsAsync::NotAsync, } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b172b863ab61..7e3ada9c1234b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1664,7 +1664,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime.ident, )); - // Now make an arg that we can use for the substs of the opaque tykind. + // Now make an arg that we can use for the generic params of the opaque tykind. let id = self.next_node_id(); let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res); let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id); @@ -1824,7 +1824,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let fn_def_id = self.local_def_id(fn_node_id); - self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind) + self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind, fn_span) } else { match &decl.output { FnRetTy::Ty(ty) => { @@ -1901,8 +1901,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, fn_kind: FnDeclKind, + fn_span: Span, ) -> hir::FnRetTy<'hir> { - let span = self.lower_span(output.span()); + let span = self.lower_span(fn_span); let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); let captured_lifetimes: Vec<_> = self diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7bc685a545014..743fad8e86502 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -52,7 +52,8 @@ struct AstValidator<'a> { /// Are we inside a trait impl? in_trait_impl: bool, - in_const_trait_impl: bool, + /// Are we inside a const trait defn or impl? + in_const_trait_or_impl: bool, has_proc_macro_decls: bool, @@ -78,11 +79,19 @@ impl<'a> AstValidator<'a> { f: impl FnOnce(&mut Self), ) { let old = mem::replace(&mut self.in_trait_impl, is_in); - let old_const = - mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_)))); + let old_const = mem::replace( + &mut self.in_const_trait_or_impl, + matches!(constness, Some(Const::Yes(_))), + ); f(self); self.in_trait_impl = old; - self.in_const_trait_impl = old_const; + self.in_const_trait_or_impl = old_const; + } + + fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) { + let old = mem::replace(&mut self.in_const_trait_or_impl, is_const); + f(self); + self.in_const_trait_or_impl = old; } fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) { @@ -933,23 +942,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => { - if *is_auto == IsAuto::Yes { - // Auto traits cannot have generics, super traits nor contain items. - self.deny_generic_params(generics, item.ident.span); - self.deny_super_traits(bounds, item.ident.span); - self.deny_where_clause(&generics.where_clause, item.ident.span); - self.deny_items(items, item.ident.span); - } + let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait); + self.with_in_trait(is_const_trait, |this| { + if *is_auto == IsAuto::Yes { + // Auto traits cannot have generics, super traits nor contain items. + this.deny_generic_params(generics, item.ident.span); + this.deny_super_traits(bounds, item.ident.span); + this.deny_where_clause(&generics.where_clause, item.ident.span); + this.deny_items(items, item.ident.span); + } - // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound - // context for the supertraits. - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - self.visit_generics(generics); - self.with_tilde_const_allowed(|this| { - walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) + // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound + // context for the supertraits. + this.visit_vis(&item.vis); + this.visit_ident(item.ident); + this.visit_generics(generics); + this.with_tilde_const_allowed(|this| { + walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) + }); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); }); - walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again } @@ -1278,7 +1290,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. })) - || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))); + || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); @@ -1363,7 +1375,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_ty, ty); } AssocItemKind::Fn(box Fn { sig, generics, body, .. }) - if self.in_const_trait_impl + if self.in_const_trait_or_impl || ctxt == AssocCtxt::Trait || matches!(sig.header.constness, Const::Yes(_)) => { @@ -1510,7 +1522,7 @@ pub fn check_crate( features, extern_mod: None, in_trait_impl: false, - in_const_trait_impl: false, + in_const_trait_or_impl: false, has_proc_macro_decls: false, outer_impl_trait: None, disallow_tilde_const: None, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 8405ae6ff8e8b..5d279943f1e83 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -578,11 +578,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } } - // All uses of `gate_all!` below this point were added in #65742, + // All uses of `gate_all_legacy_dont_use!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). // We emit an early future-incompatible warning for these. // New syntax gates should go above here to get a hard error gate. - macro_rules! gate_all { + macro_rules! gate_all_legacy_dont_use { ($gate:ident, $msg:literal) => { for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg); @@ -590,13 +590,20 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { }; } - gate_all!(trait_alias, "trait aliases are experimental"); - gate_all!(associated_type_bounds, "associated type bounds are unstable"); - gate_all!(return_type_notation, "return type notation is experimental"); - gate_all!(decl_macro, "`macro` is experimental"); - gate_all!(box_patterns, "box pattern syntax is experimental"); - gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); - gate_all!(try_blocks, "`try` blocks are unstable"); + gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); + gate_all_legacy_dont_use!(associated_type_bounds, "associated type bounds are unstable"); + // Despite being a new feature, `where T: Trait`, which is RTN syntax now, + // used to be gated under associated_type_bounds, which are right above, so RTN needs to + // be too. + gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental"); + gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); + gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); + gate_all_legacy_dont_use!( + exclusive_range_pattern, + "exclusive range pattern syntax is experimental" + ); + gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); + gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); visit::walk_crate(&mut visitor, krate); } diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 2c4c3a0c2635b..a14d279681792 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [lib] [dependencies] +rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_serialize = { path = "../rustc_serialize" } -rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } -rustc_span = { path = "../rustc_span" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } +rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } -rustc_ast = { path = "../rustc_ast" } +rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index ca4b3662a089f..f013ff45a4fe5 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -162,7 +162,7 @@ pub enum StabilityLevel { is_soft: bool, /// If part of a feature is stabilized and a new feature is added for the remaining parts, /// then the `implied_by` attribute is used to indicate which now-stable feature previously - /// contained a item. + /// contained an item. /// /// ```pseudo-Rust /// #[unstable(feature = "foo", issue = "...")] @@ -353,28 +353,28 @@ pub fn find_body_stability( body_stab } +fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option) -> Option<()> { + if item.is_some() { + handle_errors( + &sess.parse_sess, + meta.span, + AttrError::MultipleItem(pprust::path_to_string(&meta.path)), + ); + None + } else if let Some(v) = meta.value_str() { + *item = Some(v); + Some(()) + } else { + sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); + None + } +} + /// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and /// its stability information. fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> { let meta = attr.meta()?; let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None }; - let insert_or_error = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors( - &sess.parse_sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), - ); - return false; - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); - false - } - }; let mut feature = None; let mut since = None; @@ -389,16 +389,8 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit }; match mi.name_or_empty() { - sym::feature => { - if !insert_or_error(mi, &mut feature) { - return None; - } - } - sym::since => { - if !insert_or_error(mi, &mut since) { - return None; - } - } + sym::feature => insert_or_error(sess, mi, &mut feature)?, + sym::since => insert_or_error(sess, mi, &mut since)?, _ => { handle_errors( &sess.parse_sess, @@ -438,23 +430,6 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> { let meta = attr.meta()?; let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None }; - let insert_or_error = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors( - &sess.parse_sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), - ); - return false; - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); - false - } - }; let mut feature = None; let mut reason = None; @@ -473,20 +448,10 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil }; match mi.name_or_empty() { - sym::feature => { - if !insert_or_error(mi, &mut feature) { - return None; - } - } - sym::reason => { - if !insert_or_error(mi, &mut reason) { - return None; - } - } + sym::feature => insert_or_error(sess, mi, &mut feature)?, + sym::reason => insert_or_error(sess, mi, &mut reason)?, sym::issue => { - if !insert_or_error(mi, &mut issue) { - return None; - } + insert_or_error(sess, mi, &mut issue)?; // These unwraps are safe because `insert_or_error` ensures the meta item // is a name/value pair string literal. @@ -515,11 +480,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil } is_soft = true; } - sym::implied_by => { - if !insert_or_error(mi, &mut implied_by) { - return None; - } - } + sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?, _ => { handle_errors( &sess.parse_sess, @@ -846,7 +807,7 @@ pub fn find_deprecation( ), ); } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem2 { + sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span, }); } diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index ee79545e304ae..86f27254db25c 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -165,15 +165,6 @@ pub(crate) struct MissingIssue { pub span: Span, } -// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider -// changing this to `IncorrectMetaItem`. See #51489. -#[derive(Diagnostic)] -#[diag(attr_incorrect_meta_item, code = "E0551")] -pub(crate) struct IncorrectMetaItem2 { - #[primary_span] - pub span: Span, -} - // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(Diagnostic)] diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 48d09f2c2b2a4..4488276e0e7a6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1364,7 +1364,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.note(format!( "a for loop advances the iterator for you, the result is stored in `{loop_bind}`." )); - err.help("if you want to call `next` on a iterator within the loop, consider using `while let`."); + err.help("if you want to call `next` on an iterator within the loop, consider using `while let`."); } } @@ -2828,6 +2828,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } + | ProjectionElem::Subtype(_) | ProjectionElem::Index(_) => kind, }, place_ty.projection_ty(tcx, elem), diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 099e07e88414a..c3cf7db32b149 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -13,7 +13,7 @@ use rustc_index::IndexSlice; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, + AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; @@ -101,12 +101,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let terminator = self.body[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { - func: Operand::Constant(box Constant { literal, .. }), + func: Operand::Constant(box ConstOperand { const_, .. }), args, .. } = &terminator.kind { - if let ty::FnDef(id, _) = *literal.ty().kind() { + if let ty::FnDef(id, _) = *const_.ty().kind() { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { @@ -242,6 +242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ProjectionElem::Downcast(..) if opt.including_downcast => return None, ProjectionElem::Downcast(..) => (), ProjectionElem::OpaqueCast(..) => (), + ProjectionElem::Subtype(..) => (), ProjectionElem::Field(field, _ty) => { // FIXME(project-rfc_2229#36): print capture precisely here. if let Some(field) = self.is_upvar_field_projection(PlaceRef { @@ -322,7 +323,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx) } ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx), - ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty), + ProjectionElem::Subtype(ty) | ProjectionElem::OpaqueCast(ty) => { + PlaceTy::from_ty(*ty) + } ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type), }, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a0edeec59d058..e6bde6a8c54dc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -159,6 +159,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { [ .., ProjectionElem::Index(_) + | ProjectionElem::Subtype(_) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::OpaqueCast { .. } | ProjectionElem::Subslice { .. } @@ -1358,9 +1359,9 @@ fn suggest_ampmut<'tcx>( None => (false, decl_span), }; - // if the binding already exists and is a reference with a explicit + // if the binding already exists and is a reference with an explicit // lifetime, then we can suggest adding ` mut`. this is special-cased from - // the path without a explicit lifetime. + // the path without an explicit lifetime. if let Ok(src) = tcx.sess.source_map().span_to_snippet(span) && src.starts_with("&'") // note that `& 'a T` is invalid so this is correct. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 2ea399789b9a3..27072a60f65f0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -245,7 +245,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; diag.span_note( *trait_span, - format!("due to current limitations in the borrow checker, this implies a `'static` lifetime") + "due to current limitations in the borrow checker, this implies a `'static` lifetime" ); let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) else { return; }; let Def(_, trait_res_defid) = trait_ref.path.res else { return; }; @@ -277,7 +277,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - format!("consider restricting the type parameter to the `'static` lifetime"), + "consider restricting the type parameter to the `'static` lifetime", suggestions, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index b40e89e471d65..55d581b3ab123 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -27,7 +27,7 @@ pub(crate) struct RegionName { /// This helps to print the right kinds of diagnostics. #[derive(Debug, Clone)] pub(crate) enum RegionNameSource { - /// A bound (not free) region that was substituted at the def site (not an HRTB). + /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyBoundRegion(Span), /// A free region that the user has a name (`'a`) for. NamedFreeRegion(Span), @@ -302,7 +302,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { if free_region.bound_region.is_named() { // A named region that is actually named. Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) }) - } else if let hir::IsAsync::Async = tcx.asyncness(self.mir_hir_id().owner) { + } else if tcx.asyncness(self.mir_hir_id().owner).is_async() { // If we spuriously thought that the region is named, we should let the // system generate a true name for error messages. Currently this can // happen if we have an elided name in an async fn for example: the @@ -354,7 +354,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }) } - ty::BoundRegionKind::BrAnon(..) => None, + ty::BoundRegionKind::BrAnon => None, }, ty::ReLateBound(..) @@ -516,7 +516,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // be the same as those of the ADT. // FIXME: We should be able to do something similar to // match_adt_and_segment in this case. - Res::Def(DefKind::TyAlias { .. }, _) => (), + Res::Def(DefKind::TyAlias, _) => (), _ => { if let Some(last_segment) = path.segments.last() { if let Some(highlight) = self.match_adt_and_segment( @@ -619,7 +619,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // programs, so we need to use delay_span_bug here. See #82126. self.infcx.tcx.sess.delay_span_bug( hir_arg.span(), - format!("unmatched subst and hir arg: found {kind:?} vs {hir_arg:?}"), + format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8115c61e89d30..9c77767e7a70e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1803,6 +1803,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { for (place_base, elem) in place.iter_projections().rev() { match elem { ProjectionElem::Index(_/*operand*/) | + ProjectionElem::Subtype(_) | ProjectionElem::OpaqueCast(_) | ProjectionElem::ConstantIndex { .. } | // assigning to P[i] requires P to be valid. @@ -1966,7 +1967,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => { let is_local_mutation_allowed = match mut_borrow_kind { - // `ClosureCapture` is used for mutable variable with a immutable binding. + // `ClosureCapture` is used for mutable variable with an immutable binding. // This is only behaviour difference between `ClosureCapture` and mutable borrows. MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes, MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => { @@ -2191,6 +2192,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } + | ProjectionElem::Subtype(..) | ProjectionElem::OpaqueCast { .. } | ProjectionElem::Downcast(..) => { let upvar_field_projection = self.is_upvar_field_projection(place); diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index c02f6f3b68782..539d0837659c8 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -249,6 +249,7 @@ fn place_components_conflict<'tcx>( | (ProjectionElem::ConstantIndex { .. }, _, _) | (ProjectionElem::Subslice { .. }, _, _) | (ProjectionElem::OpaqueCast { .. }, _, _) + | (ProjectionElem::Subtype(_), _, _) | (ProjectionElem::Downcast { .. }, _, _) => { // Recursive case. This can still be disjoint on a // further iteration if this a shallow access and @@ -508,6 +509,7 @@ fn place_projection_conflict<'tcx>( | ProjectionElem::Field(..) | ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subtype(_) | ProjectionElem::OpaqueCast { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Downcast(..), diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 6f28134986376..e9c9709bd1f1a 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -89,6 +89,9 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { cursor = cursor_base; continue 'cursor; } + ProjectionElem::Subtype(..) => { + panic!("Subtype projection is not allowed before borrow check") + } ProjectionElem::Deref => { // (handled below) } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 1049e7a8bbe35..852935676b6f3 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2250,7 +2250,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { // Query canonicalization can create local superuniverses (for example in - // `InferCtx::query_response_substitution_guess`), but they don't have an associated + // `InferCtx::query_response_instantiation_guess`), but they don't have an associated // `UniverseInfo` explaining why they were created. // This can cause ICEs if these causes are accessed in diagnostics, for example in issue // #114907 where this happens via liveness and dropck outlives results. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index b7da15af6dc31..ff04b0237c244 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -368,7 +368,7 @@ fn check_opaque_type_well_formed<'tcx>( if errors.is_empty() { Ok(definition_ty) } else { - Err(infcx.err_ctxt().report_fulfillment_errors(&errors)) + Err(infcx.err_ctxt().report_fulfillment_errors(errors)) } } diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 4c69ea843c724..5d6f5cc896782 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -4,11 +4,10 @@ use crate::BorrowckInferCtxt; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; -use rustc_middle::mir::Constant; -use rustc_middle::mir::{Body, Location, Promoted}; +use rustc_middle::mir::{Body, ConstOperand, Location, Promoted}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc_span::{Span, Symbol}; +use rustc_span::Symbol; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. @@ -29,21 +28,15 @@ pub fn renumber_mir<'tcx>( renumberer.visit_body(body); } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub(crate) enum BoundRegionInfo { - Name(Symbol), - Span(Span), -} - #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub(crate) enum RegionCtxt { Location(Location), TyContext(TyContext), Free(Symbol), - Bound(BoundRegionInfo), - LateBound(BoundRegionInfo), + Bound(Symbol), + LateBound(Symbol), Existential(Option), - Placeholder(BoundRegionInfo), + Placeholder(Symbol), Unknown, } @@ -117,9 +110,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) { - let literal = constant.literal; - constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location)); + fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) { + let const_ = constant.const_; + constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location)); debug!("constant: {:#?}", constant); } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0f661421cdcf0..e7b1a489f5d7c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -302,11 +302,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { self.sanitize_place(place, location, context); } - fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) { debug!(?constant, ?location, "visit_constant"); self.super_constant(constant, location); - let ty = self.sanitize_type(constant, constant.literal.ty()); + let ty = self.sanitize_type(constant, constant.const_.ty()); self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| { let live_region_vid = @@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( - constant.literal.ty(), + constant.const_.ty(), ty::Variance::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![] }, locations, @@ -340,20 +340,20 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { constant, "bad constant user type {:?} vs {:?}: {:?}", annotation, - constant.literal.ty(), + constant.const_.ty(), terr, ); } } else { let tcx = self.tcx(); - let maybe_uneval = match constant.literal { - ConstantKind::Ty(ct) => match ct.kind() { + let maybe_uneval = match constant.const_ { + Const::Ty(ct) => match ct.kind() { ty::ConstKind::Unevaluated(_) => { - bug!("should not encounter unevaluated ConstantKind::Ty here, got {:?}", ct) + bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct) } _ => None, }, - ConstantKind::Unevaluated(uv, _) => Some(uv), + Const::Unevaluated(uv, _) => Some(uv), _ => None, }; @@ -384,7 +384,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { check_err(self, promoted_body, ty, promoted_ty); } else { self.cx.ascribe_user_type( - constant.literal.ty(), + constant.const_.ty(), UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), locations.span(&self.cx.body), ); @@ -392,7 +392,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity(); let normalized_ty = self.cx.normalize(unnormalized_ty, locations); - let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty; + let literal_ty = constant.const_.ty().builtin_deref(true).unwrap().ty; if let Err(terr) = self.cx.eq_types( literal_ty, @@ -404,7 +404,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() { + if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args); self.cx.normalize_and_prove_instantiated_predicates( def_id, @@ -716,6 +716,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } PlaceTy::from_ty(fty) } + ProjectionElem::Subtype(_) => { + bug!("ProjectionElem::Subtype shouldn't exist in borrowck") + } ProjectionElem::OpaqueCast(ty) => { let ty = self.sanitize_type(place, ty); let ty = self.cx.normalize(ty, location); @@ -1007,7 +1010,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } pub(super) fn register_predefined_opaques_in_new_solver(&mut self) { - // OK to use the identity substitutions for each opaque type key, since + // OK to use the identity arguments for each opaque type key, since // we remap opaques from HIR typeck back to their definition params. let opaques: Vec<_> = self .infcx @@ -1367,14 +1370,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } }; let (sig, map) = tcx.replace_late_bound_regions(sig, |br| { - use crate::renumber::{BoundRegionInfo, RegionCtxt}; + use crate::renumber::RegionCtxt; let region_ctxt_fn = || { let reg_info = match br.kind { - ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span), - ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon), - ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name), - ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), + ty::BoundRegionKind::BrAnon => sym::anon, + ty::BoundRegionKind::BrNamed(_, name) => name, + ty::BoundRegionKind::BrEnv => sym::env, }; RegionCtxt::LateBound(reg_info) @@ -1801,9 +1803,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!(?op, ?location, "check_operand"); if let Operand::Constant(constant) = op { - let maybe_uneval = match constant.literal { - ConstantKind::Val(..) | ConstantKind::Ty(_) => None, - ConstantKind::Unevaluated(uv, _) => Some(uv), + let maybe_uneval = match constant.const_ { + Const::Val(..) | Const::Ty(_) => None, + Const::Unevaluated(uv, _) => Some(uv), }; if let Some(uv) = maybe_uneval { @@ -2564,6 +2566,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | ProjectionElem::Subslice { .. } => { // other field access } + ProjectionElem::Subtype(_) => { + bug!("ProjectionElem::Subtype shouldn't exist in borrowck") + } } } } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index e0c6295627bbf..c1f82e19c02e2 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -11,7 +11,7 @@ use rustc_span::{Span, Symbol}; use crate::constraints::OutlivesConstraint; use crate::diagnostics::UniverseInfo; -use crate::renumber::{BoundRegionInfo, RegionCtxt}; +use crate::renumber::RegionCtxt; use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker}; impl<'a, 'tcx> TypeChecker<'a, 'tcx> { @@ -126,10 +126,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> .placeholder_region(self.type_checker.infcx, placeholder); let reg_info = match placeholder.bound.kind { - ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span), - ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon), - ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name), - ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), + ty::BoundRegionKind::BrAnon => sym::anon, + ty::BoundRegionKind::BrNamed(_, name) => name, + ty::BoundRegionKind::BrEnv => sym::env, }; if cfg!(debug_assertions) { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 3b5f1178db520..c73192f440451 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -28,7 +28,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::Symbol; use std::iter; -use crate::renumber::{BoundRegionInfo, RegionCtxt}; +use crate::renumber::RegionCtxt; use crate::BorrowckInferCtxt; #[derive(Debug)] @@ -164,7 +164,7 @@ struct UniversalRegionIndices<'tcx> { /// be able to map them to our internal `RegionVid`. This is /// basically equivalent to an `GenericArgs`, except that it also /// contains an entry for `ReStatic` -- it might be nice to just - /// use a args, and then handle `ReStatic` another way. + /// use an args, and then handle `ReStatic` another way. indices: FxHashMap, RegionVid>, /// The vid assigned to `'static`. Used only for diagnostics. @@ -290,7 +290,7 @@ impl<'tcx> UniversalRegions<'tcx> { (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } - /// Returns `true` if `r` is classified as an local region. + /// Returns `true` if `r` is classified as a local region. pub fn is_local_free_region(&self, r: RegionVid) -> bool { self.region_classification(r) == Some(RegionClassification::Local) } @@ -446,9 +446,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { if !indices.indices.contains_key(&r) { let region_vid = { let name = r.get_name_or_anon(); - self.infcx.next_nll_region_var(FR, || { - RegionCtxt::LateBound(BoundRegionInfo::Name(name)) - }) + self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) }; debug!(?region_vid); @@ -480,9 +478,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { if !indices.indices.contains_key(&r) { let region_vid = { let name = r.get_name_or_anon(); - self.infcx.next_nll_region_var(FR, || { - RegionCtxt::LateBound(BoundRegionInfo::Name(name)) - }) + self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) }; debug!(?region_vid); @@ -580,7 +576,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } - BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { + BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => { let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); if self.mir_def.to_def_id() == typeck_root_def_id { let args = @@ -643,10 +639,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); - let subst_mapping = - iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); + let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); - UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } + UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static } } fn compute_inputs_and_output( @@ -796,7 +791,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { _ => sym::anon, }; - self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name))) + self.next_nll_region_var(origin, || RegionCtxt::Bound(name)) }; indices.insert_late_bound_region(liberated_region, region_vid.as_var()); @@ -826,9 +821,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { if !indices.indices.contains_key(&r) { let region_vid = { let name = r.get_name_or_anon(); - self.next_nll_region_var(FR, || { - RegionCtxt::LateBound(BoundRegionInfo::Name(name)) - }) + self.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) }; debug!(?region_vid); @@ -848,9 +841,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { if !indices.indices.contains_key(&r) { let region_vid = { let name = r.get_name_or_anon(); - self.next_nll_region_var(FR, || { - RegionCtxt::LateBound(BoundRegionInfo::Name(name)) - }) + self.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) }; indices.insert_late_bound_region(r, region_vid.as_var()); diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 2c8e6f99c6739..8027ca2e7bb47 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -41,7 +41,7 @@ pub fn expand_deriving_const_param_ty( path: path_std!(marker::ConstParamTy), skip_path_as_bound: false, needs_copy_as_bound_if_packed: false, - additional_bounds: Vec::new(), + additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))], supports_unions: false, methods: Vec::new(), associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 53ff089d7b4eb..9c57f68f0b81e 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -169,29 +169,15 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> { } } -// Beware, this is duplicated in librustc_passes/entry.rs (with -// `rustc_hir::Item`), so make sure to keep them in sync. -fn entry_point_type(item: &ast::Item, depth: usize) -> EntryPointType { +fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType { match item.kind { ast::ItemKind::Fn(..) => { - if attr::contains_name(&item.attrs, sym::start) { - EntryPointType::Start - } else if attr::contains_name(&item.attrs, sym::rustc_main) { - EntryPointType::RustcMainAttr - } else if item.ident.name == sym::main { - if depth == 0 { - // This is a top-level function so can be 'main' - EntryPointType::MainNamed - } else { - EntryPointType::OtherMain - } - } else { - EntryPointType::None - } + rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name)) } _ => EntryPointType::None, } } + /// A folder used to remove any entry points (like fn main) because the harness /// generator will provide its own struct EntryPointCleaner<'a> { @@ -210,7 +196,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { // Remove any #[rustc_main] or #[start] from the AST so it doesn't // clash with the one we're going to add, but mark it as // #[allow(dead_code)] to avoid printing warnings. - let item = match entry_point_type(&item, self.depth) { + let item = match entry_point_type(&item, self.depth == 0) { EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => { item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { let allow_dead_code = attr::mk_attr_nested_word( diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index af8e43da4eafe..7c324421be9ca 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arbitrary" @@ -25,12 +25,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bitflags" version = "1.3.2" @@ -39,9 +33,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "cfg-if" @@ -51,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec27af72e56235eb326b5bf2de4e70ab7c5ac1fb683a1829595badaf821607fd" +checksum = "03b9d1a9e776c27ad55d7792a380785d1fe8c2d7b099eed8dbd8f4af2b598192" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2231e12925e6c5f4bc9c95b62a798eea6ed669a95bc3e00f8b2adb3b7b9b7a80" +checksum = "5528483314c2dd5da438576cd8a9d0b3cedad66fb8a4727f90cd319a81950038" dependencies = [ "bumpalo", "cranelift-bforest", @@ -72,7 +66,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.13.2", + "hashbrown 0.14.0", "log", "regalloc2", "smallvec", @@ -81,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b00b8dfb3aab85674a534677e7ca08854b503f164a70ec0634fce80996e2c" +checksum = "0f46a8318163f7682e35b8730ba93c1b586a2da8ce12a0ed545efc1218550f70" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0feb9ecc8193ef5cb04f494c5bd835e5bfec4bde726e7ac0444fc9dd76229e" +checksum = "37d1239cfd50eecfaed468d46943f8650e32969591868ad50111613704da6c70" [[package]] name = "cranelift-control" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72eedd2afcf5fee1e042eaaf18d3750e48ad0eca364a9f5971ecfdd5ef85bf71" +checksum = "bcc530560c8f16cc1d4dd7ea000c56f519c60d1a914977abe849ce555c35a61d" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7af19157be42671073cf8c2a52d6a4ae1e7b11f1dcb4131fede356d9f91c29dd" +checksum = "f333fa641a9ad2bff0b107767dcb972c18c2bfab7969805a1d7e42449ccb0408" [[package]] name = "cranelift-frontend" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dc7636c5fad156be7d9ae691cd1aaecd97326caf2ab534ba168056d56aa76c" +checksum = "06abf6563015a80f03f8bc4df307d0a81363f4eb73108df3a34f6e66fb6d5307" dependencies = [ "cranelift-codegen", "log", @@ -123,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1111aea4fb6fade5779903f184249a3fc685a799fe4ec59126f9af59c7c2a74" +checksum = "0eb29d0edc8a5c029ed0f7ca77501f272738e3c410020b4a00f42ffe8ad2a8aa" [[package]] name = "cranelift-jit" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dadf88076317f6286ec77ebbe65978734fb43b6befdc96f52ff4c4c511841644" +checksum = "d16e8c5e212b1e63658aada17553497e7a259acab61f044d1f185527efa609fb" dependencies = [ "anyhow", "cranelift-codegen", @@ -149,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6bae8a82dbf82241b1083e57e06870d2c2bdc9852727be99d58477513816953" +checksum = "d3b5fd273e1a959e920c7a9d790b1646d31acc8782bb549bad5ab85dd2fc9aa7" dependencies = [ "anyhow", "cranelift-codegen", @@ -160,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecfc01a634448468a698beac433d98040033046678a0eed3ca39a3a9f63ae86" +checksum = "006056a7fa920870bad06bf8e1b3033d70cbb7ee625b035efa9d90882a931868" dependencies = [ "cranelift-codegen", "libc", @@ -171,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee14a7276999f0dcaae2de84043e2c2de50820fb89b3db56fab586a4ad26734" +checksum = "9c8be1b0e7720f30fec31be0c0b0b23caef2a73fa751190c6a251c1362e8f8c9" dependencies = [ "anyhow", "cranelift-codegen", @@ -195,33 +189,27 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" dependencies = [ "fallible-iterator", - "indexmap 1.9.3", + "indexmap", "stable_deref_trait", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.13.2" @@ -236,15 +224,8 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "ahash", ] [[package]] @@ -259,9 +240,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" @@ -275,12 +256,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mach" @@ -293,27 +271,27 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "object" -version = "0.30.4" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "crc32fast", - "hashbrown 0.13.2", - "indexmap 1.9.3", + "hashbrown 0.14.0", + "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "regalloc2" @@ -357,7 +335,7 @@ dependencies = [ "cranelift-native", "cranelift-object", "gimli", - "indexmap 2.0.0", + "indexmap", "libloading", "object", "smallvec", @@ -366,15 +344,15 @@ dependencies = [ [[package]] name = "slice-group-by" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "stable_deref_trait" @@ -396,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "11.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34eb67f0829a5614ec54716c8e0c9fe68fab7b9df3686c85f719c9d247f7169" +checksum = "c6ff5f3707a5e3797deeeeac6ac26b2e1dd32dbc06693c0ab52e8ac4d18ec706" dependencies = [ "cfg-if", "libc", @@ -438,9 +416,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -453,42 +431,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 8ded81d7399b5..28a37b7995b77 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.98", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.98" } -cranelift-module = { version = "0.98" } -cranelift-native = { version = "0.98" } -cranelift-jit = { version = "0.98", optional = true } -cranelift-object = { version = "0.98" } +cranelift-codegen = { version = "0.100", features = ["unwind", "all-arch"] } +cranelift-frontend = { version = "0.100" } +cranelift-module = { version = "0.100" } +cranelift-native = { version = "0.100" } +cranelift-jit = { version = "0.100", optional = true } +cranelift-object = { version = "0.100" } target-lexicon = "0.12.0" -gimli = { version = "0.27.2", default-features = false, features = ["write"]} -object = { version = "0.30.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +gimli = { version = "0.28", default-features = false, features = ["write"]} +object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.7.3", optional = true } diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 62eaef359af92..6f2027be96de9 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -60,18 +60,14 @@ You need to do this steps to successfully compile and use the cranelift backend 2. Run `python x.py setup` and choose option for compiler (`b`). 3. Build compiler and necessary tools: `python x.py build --stage=2 compiler library/std src/tools/rustdoc src/tools/rustfmt` * (Optional) You can also build cargo by adding `src/tools/cargo` to previous command. -4. Copy exectutable files from `./build/host/stage2-tools//release` -to `./build/host/stage2/bin/`. Note that you would need to do this every time you rebuilt `rust` repository. -5. Copy cargo from another toolchain: `cp $(rustup which cargo) .build//stage2/bin/cargo` - * Another option is to build it at step 3 and copy with other executables at step 4. -6. Link your new `rustc` to toolchain: `rustup toolchain link stage2 ./build/host/stage2/`. -7. (Windows only) compile the build system: `rustc +stage2 -O build_system/main.rs -o y.exe`. -8. You need to prefix every `./y.sh` (or `y` if you built `build_system/main.rs` as `y`) command by `rustup run stage2` to make cg_clif use your local changes in rustc. - +4. Copy cargo from a nightly toolchain: `cp $(rustup +nightly which cargo) ./build/host/stage2/bin/cargo`. Note that you would need to do this every time you rebuilt `rust` repository. +5. Link your new `rustc` to toolchain: `rustup toolchain link stage2 ./build/host/stage2/`. +6. (Windows only) compile the build system: `rustc +stage2 -O build_system/main.rs -o y.exe`. +7. You need to prefix every `./y.sh` (or `y` if you built `build_system/main.rs` as `y`) command by `rustup run stage2` to make cg_clif use your local changes in rustc. * `rustup run stage2 ./y.sh prepare` * `rustup run stage2 ./y.sh build` * (Optional) run tests: `rustup run stage2 ./y.sh test` -9. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`. +8. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`. ## Configuration diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs index e434c36f99227..d90111adf7761 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -20,6 +20,8 @@ pub(crate) fn build_backend( let mut rustflags = rustflags_from_env("RUSTFLAGS"); + rustflags.push("-Zallow-features=rustc_private".to_owned()); + if is_ci() { // Deny warnings on CI rustflags.push("-Dwarnings".to_owned()); diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs index 798ae9dbd5006..e8cf486e966ed 100644 --- a/compiler/rustc_codegen_cranelift/build_system/main.rs +++ b/compiler/rustc_codegen_cranelift/build_system/main.rs @@ -55,7 +55,7 @@ enum CodegenBackend { } fn main() { - if env::var("RUST_BACKTRACE").is_err() { + if env::var_os("RUST_BACKTRACE").is_none() { env::set_var("RUST_BACKTRACE", "1"); } env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1"); diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index 165296cb4a98f..16e7a4bafaee9 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -122,10 +122,10 @@ impl GitRepo { if download_dir.exists() { let actual_hash = format!("{:016x}", hash_dir(&download_dir)); if actual_hash == self.content_hash { - println!("[FRESH] {}", download_dir.display()); + eprintln!("[FRESH] {}", download_dir.display()); return; } else { - println!( + eprintln!( "Mismatched content hash for {download_dir}: {actual_hash} != {content_hash}. Downloading again.", download_dir = download_dir.display(), content_hash = self.content_hash, @@ -150,7 +150,7 @@ impl GitRepo { let actual_hash = format!("{:016x}", hash_dir(&download_dir)); if actual_hash != self.content_hash { - println!( + eprintln!( "Download of {download_dir} failed with mismatched content hash: {actual_hash} != {content_hash}", download_dir = download_dir.display(), content_hash = self.content_hash, diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index e7bd8b1278c66..95ff6b754220a 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -9,7 +9,7 @@ use crate::path::{Dirs, RelPath}; use crate::prepare::{apply_patches, GitRepo}; use crate::rustc_info::get_default_sysroot; use crate::shared_utils::rustflags_from_env; -use crate::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler, LogGroup}; +use crate::utils::{spawn_and_wait, CargoProject, Compiler, LogGroup}; use crate::{CodegenBackend, SysrootKind}; static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example"); @@ -101,13 +101,11 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"), ]; -// FIXME(rust-random/rand#1293): Newer rand versions fail to test on Windows. Update once this is -// fixed. pub(crate) static RAND_REPO: GitRepo = GitRepo::github( "rust-random", "rand", - "50b9a447410860af8d6db9a208c3576886955874", - "446203b96054891e", + "f3dd0b885c4597b9617ca79987a0dd899ab29fcb", + "3f869e4fcd602b66", "rand", ); @@ -116,8 +114,8 @@ pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir() pub(crate) static REGEX_REPO: GitRepo = GitRepo::github( "rust-lang", "regex", - "32fed9429eafba0ae92a64b01796a0c5a75b88c8", - "fcc4df7c5b902633", + "061ee815ef2c44101dba7b0b124600fcb03c1912", + "dc26aefbeeac03ca", "regex", ); @@ -126,8 +124,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "7c7dbe0c505ccbc02ff30c1e37381ab1d47bf46f", - "5bcc9c544f6fa7bd", + "4825b2a64d765317066948867e8714674419359b", + "8b188cc41f5af835", "portable-simd", ); @@ -180,40 +178,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.regex-shootout-regex-dna", &|runner| { - REGEX_REPO.patch(&runner.dirs); - - REGEX.clean(&runner.dirs); - - let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs); - build_cmd.arg("--example").arg("shootout-regex-dna"); - spawn_and_wait(build_cmd); - - if runner.is_native { - let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs); - run_cmd.arg("--example").arg("shootout-regex-dna"); - - let input = fs::read_to_string( - REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"), - ) - .unwrap(); - let expected = fs::read_to_string( - REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt"), - ) - .unwrap(); - - let output = spawn_and_wait_with_input(run_cmd, input); - - let output_matches = expected.lines().eq(output.lines()); - if !output_matches { - println!("Output files don't match!"); - println!("Expected Output:\n{}", expected); - println!("Actual Output:\n{}", output); - - std::process::exit(1); - } - } - }), TestCase::custom("test.regex", &|runner| { REGEX_REPO.patch(&runner.dirs); @@ -223,7 +187,22 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs); // regex-capi and regex-debug don't have any tests. Nor do they contain any code // that is useful to test with cg_clif. Skip building them to reduce test time. - run_cmd.args(["-p", "regex", "-p", "regex-syntax", "--", "-q"]); + run_cmd.args([ + "-p", + "regex", + "-p", + "regex-syntax", + "--release", + "--all-targets", + "--", + "-q", + ]); + spawn_and_wait(run_cmd); + + let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs); + // don't run integration tests for regex-autonata. they take like 2min each without + // much extra coverage of simd usage. + run_cmd.args(["-p", "regex-automata", "--release", "--lib", "--", "-q"]); spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index 24624cdeab1f1..9f24c043a5044 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -1,8 +1,8 @@ use std::env; use std::fs; -use std::io::{self, Write}; +use std::io; use std::path::{Path, PathBuf}; -use std::process::{self, Command, Stdio}; +use std::process::{self, Command}; use std::sync::atomic::{AtomicBool, Ordering}; use crate::path::{Dirs, RelPath}; @@ -47,7 +47,7 @@ impl Compiler { self.runner = vec!["wine".to_owned()]; } _ => { - println!("Unknown non-native platform"); + eprintln!("Unknown non-native platform"); } } } @@ -197,7 +197,9 @@ pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { #[track_caller] pub(crate) fn spawn_and_wait(mut cmd: Command) { - if !cmd.spawn().unwrap().wait().unwrap().success() { + let status = cmd.spawn().unwrap().wait().unwrap(); + if !status.success() { + eprintln!("{cmd:?} exited with status {:?}", status); process::exit(1); } } @@ -207,38 +209,17 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) { pub(crate) fn retry_spawn_and_wait(tries: u64, mut cmd: Command) { for i in 1..tries + 1 { if i != 1 { - println!("Command failed. Attempt {i}/{tries}:"); + eprintln!("Command failed. Attempt {i}/{tries}:"); } if cmd.spawn().unwrap().wait().unwrap().success() { return; } std::thread::sleep(std::time::Duration::from_secs(i * 5)); } - println!("The command has failed after {tries} attempts."); + eprintln!("The command has failed after {tries} attempts."); process::exit(1); } -#[track_caller] -pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String { - let mut child = cmd - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn child process"); - - let mut stdin = child.stdin.take().expect("Failed to open stdin"); - std::thread::spawn(move || { - stdin.write_all(input.as_bytes()).expect("Failed to write to stdin"); - }); - - let output = child.wait_with_output().expect("Failed to read stdout"); - if !output.status.success() { - process::exit(1); - } - - String::from_utf8(output.stdout).unwrap() -} - pub(crate) fn remove_dir_if_exists(path: &Path) { match fs::remove_dir_all(&path) { Ok(()) => {} diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index fa1c9f4259c49..7ff805e58d967 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -46,6 +46,5 @@ aot.issue-59326 testsuite.extended_sysroot test.rust-random/rand test.libcore -test.regex-shootout-regex-dna test.regex test.portable-simd diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 34c7e44b2881c..934e4b1786faa 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -683,6 +683,12 @@ pub macro cfg() { /* compiler built-in */ } +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro asm() { + /* compiler built-in */ +} + #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] pub macro global_asm() { diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch deleted file mode 100644 index 87252df1eabe3..0000000000000 --- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Allow-internal-features.patch +++ /dev/null @@ -1,24 +0,0 @@ -From fcf75306d88e533b83eaff3f8d0ab9f307e8a84d Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Wed, 9 Aug 2023 10:01:17 +0000 -Subject: [PATCH] Allow internal features - ---- - crates/core_simd/src/lib.rs | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs -index fde406b..b386116 100644 ---- a/crates/core_simd/src/lib.rs -+++ b/crates/core_simd/src/lib.rs -@@ -19,6 +19,7 @@ - #![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")] -+#![allow(internal_features)] - //! Portable SIMD module. - - #[path = "mod.rs"] --- -2.34.1 - diff --git a/compiler/rustc_codegen_cranelift/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch b/compiler/rustc_codegen_cranelift/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch new file mode 100644 index 0000000000000..e6ebdcec783af --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch @@ -0,0 +1,25 @@ +From 5d4afb8d807d181038b6a004d17ed055a8d191b2 Mon Sep 17 00:00:00 2001 +From: bjorn3 <17426603+bjorn3@users.noreply.github.com> +Date: Mon, 2 Oct 2023 13:59:00 +0000 +Subject: [PATCH] Ignore test which gets miscompiled with llvm sysroot + +--- + regex-automata/src/util/pool.rs | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/regex-automata/src/util/pool.rs b/regex-automata/src/util/pool.rs +index c03d7b0..28b233b 100644 +--- a/regex-automata/src/util/pool.rs ++++ b/regex-automata/src/util/pool.rs +@@ -1081,6 +1081,8 @@ mod tests { + // into the pool. This in turn resulted in this test producing a data race. + #[cfg(feature = "std")] + #[test] ++ // FIXME(rustc_codegen_cranelift#1395) miscompilation of thread::scope with LLVM sysroot ++ #[ignore] + fn thread_owner_sync() { + let pool = Pool::new(|| vec!['a']); + { +-- +2.34.1 + diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch index a650e10110bf2..be29ae09bcfc6 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -19,9 +19,9 @@ index 897a5e9..331f66f 100644 #![feature(const_option_ext)] #![feature(const_result)] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] + #![cfg_attr(test, feature(cfg_match))] #![feature(int_roundings)] #![feature(slice_group_by)] - #![feature(split_array)] diff --git a/atomic.rs b/atomic.rs index b735957..ea728b6 100644 --- a/atomic.rs diff --git a/compiler/rustc_codegen_cranelift/patches/portable-simd-lock.toml b/compiler/rustc_codegen_cranelift/patches/portable-simd-lock.toml index e7db1fd2c7fb6..5c9dc7b361f96 100644 --- a/compiler/rustc_codegen_cranelift/patches/portable-simd-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/portable-simd-lock.toml @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" @@ -55,33 +55,33 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "log" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.17.2" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "ppv-lite86" @@ -91,9 +91,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -114,9 +114,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -199,15 +199,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -215,9 +215,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", @@ -230,9 +230,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", @@ -265,15 +265,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-bindgen-test" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502" +checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" dependencies = [ "console_error_panic_hook", "js-sys", @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3" +checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" dependencies = [ "proc-macro2", "quote", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/compiler/rustc_codegen_cranelift/patches/rand-lock.toml b/compiler/rustc_codegen_cranelift/patches/rand-lock.toml index 66c515731c5e3..aacf3653c169e 100644 --- a/compiler/rustc_codegen_cranelift/patches/rand-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/rand-lock.toml @@ -2,6 +2,32 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -28,12 +54,114 @@ dependencies = [ "serde", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ciborium" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" + +[[package]] +name = "ciborium-ll" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -57,9 +185,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", @@ -70,13 +198,48 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "easy-cast" version = "0.4.4" @@ -88,9 +251,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "float-ord" @@ -98,37 +261,101 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libm" @@ -138,24 +365,30 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "log" -version = "0.4.18" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", "libm", @@ -163,14 +396,60 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "libc", ] +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -179,18 +458,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -200,6 +479,7 @@ name = "rand" version = "0.9.0" dependencies = [ "bincode", + "criterion", "libc", "log", "rand_chacha", @@ -236,6 +516,7 @@ dependencies = [ "rand", "rand_pcg", "serde", + "serde_with", "special", ] @@ -270,49 +551,109 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "special" version = "0.8.1" @@ -322,25 +663,163 @@ dependencies = [ "libc", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" -version = "2.0.18" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.37", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/compiler/rustc_codegen_cranelift/patches/regex-lock.toml b/compiler/rustc_codegen_cranelift/patches/regex-lock.toml index 0e4a33b90ea1f..e0df6f9ae2671 100644 --- a/compiler/rustc_codegen_cranelift/patches/regex-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/regex-lock.toml @@ -4,51 +4,49 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0" dependencies = [ + "log", "memchr", ] [[package]] -name = "bitflags" -version = "1.3.2" +name = "anyhow" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] -name = "bzip2" -version = "0.3.3" +name = "arbitrary" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" +checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" dependencies = [ - "bzip2-sys", - "libc", + "derive_arbitrary", ] [[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" +name = "atty" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "cc", + "hermit-abi", "libc", - "pkg-config", + "winapi", ] [[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "0.1.10" +name = "bstr" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "cfg-if" @@ -57,114 +55,129 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "docopt" -version = "1.1.1" +name = "derive_arbitrary" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" +checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ - "lazy_static", - "regex 1.8.3", - "serde", - "strsim", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "filetime" -version = "0.2.21" +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "env_logger" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "windows-sys", + "atty", + "humantime", + "log", + "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "hashbrown" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] -name = "libc" -version = "0.2.144" +name = "hermit-abi" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] -name = "libpcre-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff3dd28ba96d6fe6752882f2f1b25ba8e1646448e79042442347cf3a92a6666" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "bzip2", "libc", - "pkg-config", - "tar", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "humantime" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "memmap" -version = "0.6.2" +name = "indexmap" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ - "libc", - "winapi", + "equivalent", + "hashbrown", ] [[package]] -name = "onig" -version = "3.2.2" +name = "lexopt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" + +[[package]] +name = "libc" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5eeb268a4620c74ea5768c6d2ccd492d60a47a8754666b91a46bfc35cd4d1ba" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" dependencies = [ - "bitflags", - "lazy_static", - "libc", - "onig_sys", + "log", ] [[package]] -name = "onig_sys" -version = "68.2.1" +name = "memmap2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195ebddbb56740be48042ca117b8fb6e0d99fe392191a9362d82f5f69e510379" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ - "cc", "libc", - "pkg-config", ] [[package]] -name = "pkg-config" -version = "0.3.27" +name = "once_cell" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -180,9 +193,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -205,96 +218,102 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" -version = "1.7.2" +version = "1.9.5" dependencies = [ "aho-corasick", - "lazy_static", + "anyhow", + "doc-comment", + "env_logger", "memchr", + "once_cell", "quickcheck", - "rand", - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", + "regex-test", ] [[package]] -name = "regex" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +name = "regex-automata" +version = "0.3.8" dependencies = [ - "regex-syntax 0.7.2", + "aho-corasick", + "anyhow", + "bstr", + "doc-comment", + "env_logger", + "log", + "memchr", + "quickcheck", + "regex-syntax", + "regex-test", ] [[package]] -name = "regex-benchmark" +name = "regex-cli" version = "0.1.0" dependencies = [ - "cc", - "cfg-if 0.1.10", - "docopt", - "lazy_static", - "libc", - "libpcre-sys", - "memmap", - "onig", - "pkg-config", - "regex 1.7.2", - "regex-syntax 0.6.29", - "serde", + "anyhow", + "bstr", + "lexopt", + "log", + "memmap2", + "regex", + "regex-automata", + "regex-lite", + "regex-syntax", + "tabwriter", + "textwrap", ] [[package]] -name = "regex-debug" +name = "regex-lite" version = "0.1.0" dependencies = [ - "docopt", - "regex 1.7.2", - "regex-syntax 0.6.29", - "serde", + "anyhow", + "regex-test", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" +dependencies = [ + "arbitrary", +] [[package]] -name = "regex-syntax" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +name = "regex-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "bstr", + "serde", + "toml", +] [[package]] name = "rure" version = "0.2.2" dependencies = [ "libc", - "regex 1.7.2", + "regex", ] [[package]] name = "serde" -version = "1.0.163" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -302,16 +321,19 @@ dependencies = [ ] [[package]] -name = "strsim" -version = "0.10.0" +name = "serde_spanned" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] [[package]] name = "syn" -version = "2.0.18" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -319,121 +341,117 @@ dependencies = [ ] [[package]] -name = "tar" -version = "0.4.38" +name = "tabwriter" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "08e1173ee641651a3095fe95d86ae314cd1f959888097debce3e0f9ca532eef1" dependencies = [ - "filetime", - "libc", - "xattr", + "unicode-width", ] [[package]] -name = "unicode-ident" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" +name = "termcolor" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "winapi-util", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "textwrap" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "toml" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "toml_datetime" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ - "windows-targets", + "serde", ] [[package]] -name = "windows-targets" -version = "0.48.0" +name = "toml_edit" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" +name = "unicode-width" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] -name = "windows_i686_gnu" -version = "0.48.0" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "windows_i686_msvc" -version = "0.48.0" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" +name = "winapi-util" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "xattr" -version = "0.2.3" +name = "winnow" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ - "libc", + "memchr", ] diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml index 5b79d6569bb01..de89c4f5eff81 100644 --- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.146" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" dependencies = [ "rustc-std-workspace-core", ] @@ -255,6 +255,27 @@ dependencies = [ "core", ] +[[package]] +name = "r-efi" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575fc2d9b3da54adbdfaddf6eca48fec256d977c8630a1750b8991347d1ac911" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "r-efi-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" +dependencies = [ + "compiler_builtins", + "r-efi", + "rustc-std-workspace-core", +] + [[package]] name = "rand" version = "0.8.5" @@ -340,6 +361,7 @@ version = "0.0.0" dependencies = [ "addr2line", "alloc", + "cc", "cfg-if", "compiler_builtins", "core", @@ -353,6 +375,8 @@ dependencies = [ "panic_abort", "panic_unwind", "profiler_builtins", + "r-efi", + "r-efi-alloc", "rand", "rand_xorshift", "rustc-demangle", diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 2cc5d7777a621..86ef127badd40 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-09-06" +channel = "nightly-2023-10-09" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index f782671fe36f9..03912b18ea5f2 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -100,9 +100,9 @@ fn main() -> Result<(), Box> { stack = &stack[..index + ENCODE_METADATA.len()]; } - const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::subst_and_normalize_erasing_regions"; - if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) { - stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()]; + const INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::instantiate_and_normalize_erasing_regions"; + if let Some(index) = stack.find(INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS) { + stack = &stack[..index + INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS.len()]; } const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::normalize_erasing_late_bound_regions"; diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index e6bbac647e5a2..60ac6bc9951e9 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -./y.sh build --no-unstable-features +./y.sh build echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true @@ -31,7 +31,7 @@ index d95b5b7f17f..00b6f0e3635 100644 EOF cat > config.toml </dev/null 2>&1 || cargo install ripgrep rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true -for test in $(rg --files-with-matches "lto|// needs-asm-support" tests/{codegen-units,ui,incremental}); do +for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do rm $test done -for test in tests/run-make/**/Makefile; do - if rg "# needs-asm-support" $test >/dev/null; then - rm -r $(dirname $test) - fi -done - for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do rm $test done git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed git checkout -- tests/ui/proc-macro/pretty-print-hack/ +git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # missing features @@ -35,8 +30,9 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR rm -r tests/run-make/comment-section # cg_clif doesn't yet write the .comment section # requires stack unwinding -# FIXME add needs-unwind to this test +# FIXME add needs-unwind to these tests rm -r tests/run-make/libtest-junit +rm tests/ui/asm/may_unwind.rs # extra warning about -Cpanic=abort for proc macros rm tests/ui/proc-macro/crt-static.rs @@ -77,6 +73,8 @@ rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same rm -r tests/run-make/use-extern-for-plugins # same +rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported +rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly # requires LTO rm -r tests/run-make/cdylib @@ -130,6 +128,7 @@ rm tests/ui/consts/issue-73976-monomorphic.rs # same rm tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs # same rm tests/ui/consts/const-eval/nonnull_as_ref_ub.rs # same rm tests/ui/consts/issue-94675.rs # same +rm tests/ui/associated-types/issue-85103-layout-debug.rs # same # rustdoc-clif passes extra args, suppressing the help message when no args are passed rm -r tests/run-make/issue-88756-default-output @@ -154,9 +153,12 @@ rm -r tests/run-make/output-type-permutations # same rm -r tests/run-make/used # same rm -r tests/run-make/no-alloc-shim rm -r tests/run-make/emit-to-stdout +rm -r tests/run-make/compressed-debuginfo rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported +rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug with Generator's + # bugs in the test suite # ====================== rm tests/ui/backtrace.rs # TODO warning diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 5d775b9b53229..c75ad852f82d0 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -6,6 +6,7 @@ mod returning; use std::borrow::Cow; +use cranelift_codegen::ir::{AbiParam, SigRef}; use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; @@ -13,12 +14,9 @@ use rustc_session::Session; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; -use cranelift_codegen::ir::{AbiParam, SigRef}; - use self::pass_mode::*; -use crate::prelude::*; - pub(crate) use self::returning::codegen_return; +use crate::prelude::*; fn clif_sig_from_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, @@ -30,7 +28,7 @@ fn clif_sig_from_fn_abi<'tcx>( let inputs = fn_abi.args.iter().flat_map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()); let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx); - // Sometimes the first param is an pointer to the place where the return value needs to be stored. + // Sometimes the first param is a pointer to the place where the return value needs to be stored. let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect(); Signature { params, returns, call_conv } diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 0d16da48067a0..7c9f8c1051cbb 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -1,14 +1,14 @@ //! Argument passing -use crate::prelude::*; -use crate::value_and_place::assert_assignable; - use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose}; use rustc_target::abi::call::{ ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode, Reg, RegKind, }; use smallvec::{smallvec, SmallVec}; +use crate::prelude::*; +use crate::value_and_place::assert_assignable; + pub(super) trait ArgAbiExt<'tcx> { fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]>; fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option, Vec); diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs index 646fb4a3cdc8e..0799a22c6e168 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs @@ -1,10 +1,10 @@ //! Return value handling -use crate::prelude::*; - use rustc_target::abi::call::{ArgAbi, PassMode}; use smallvec::{smallvec, SmallVec}; +use crate::prelude::*; + /// Return a place where the return value of the current function can be written to. If necessary /// this adds an extra parameter pointing to where the return value needs to be stored. pub(super) fn codegen_return_param<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 4e4c595de8257..e8af3e8c2555f 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -1,8 +1,6 @@ //! Allocator shim // Adapted from rustc -use crate::prelude::*; - use rustc_ast::expand::allocator::{ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, @@ -10,6 +8,8 @@ use rustc_ast::expand::allocator::{ use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; +use crate::prelude::*; + /// Returns whether an allocator shim was created pub(crate) fn codegen( tcx: TyCtxt<'_>, diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index 359d581c1535a..321612238ea45 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -1,11 +1,11 @@ //! SSA analysis -use crate::prelude::*; - use rustc_index::IndexVec; use rustc_middle::mir::StatementKind::*; use rustc_middle::ty::Ty; +use crate::prelude::*; + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) enum SsaKind { NotSsa, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 9b5a6b89191e1..ac7389792c80c 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -1,15 +1,14 @@ //! Codegen of a single function +use cranelift_codegen::ir::UserFuncName; +use cranelift_codegen::CodegenError; +use cranelift_module::ModuleError; use rustc_ast::InlineAsmOptions; use rustc_index::IndexVec; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use cranelift_codegen::ir::UserFuncName; -use cranelift_codegen::CodegenError; -use cranelift_module::ModuleError; - use crate::constant::ConstantCx; use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; @@ -250,17 +249,6 @@ pub(crate) fn verify_func( } fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { - if let Err(err) = - fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) - { - err.emit_err(fx.tcx); - fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); - fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - // compilation should have been aborted - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - return; - } - let arg_uninhabited = fx .mir .args_iter() @@ -875,7 +863,8 @@ pub(crate) fn codegen_place<'tcx>( PlaceElem::Deref => { cplace = cplace.place_deref(fx); } - PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty), + PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"), + PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)), PlaceElem::Field(field, _ty) => { cplace = cplace.place_field(fx, field); } diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index 6bf3a866ba46a..7e027c5f1b309 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -129,8 +129,8 @@ pub(crate) fn clif_int_or_float_cast( let (min, max) = match (to_ty, to_signed) { (types::I8, false) => (0, i64::from(u8::MAX)), (types::I16, false) => (0, i64::from(u16::MAX)), - (types::I8, true) => (i64::from(i8::MIN), i64::from(i8::MAX)), - (types::I16, true) => (i64::from(i16::MIN), i64::from(i16::MAX)), + (types::I8, true) => (i64::from(i8::MIN as u32), i64::from(i8::MAX as u32)), + (types::I16, true) => (i64::from(i16::MIN as u32), i64::from(i16::MAX as u32)), _ => unreachable!(), }; let min_val = fx.bcx.ins().iconst(types::I32, min); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index ec2da39398b2d..8958369267e5d 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -1,6 +1,5 @@ use cranelift_codegen::isa::TargetFrontendConfig; use gimli::write::FileId; - use rustc_data_structures::sync::Lrc; use rustc_index::IndexVec; use rustc_middle::ty::layout::{ @@ -204,9 +203,9 @@ pub(crate) fn type_min_max_value( (types::I8, false) | (types::I16, false) | (types::I32, false) | (types::I64, false) => { 0i64 } - (types::I8, true) => i64::from(i8::MIN), - (types::I16, true) => i64::from(i16::MIN), - (types::I32, true) => i64::from(i32::MIN), + (types::I8, true) => i64::from(i8::MIN as u8), + (types::I16, true) => i64::from(i16::MIN as u16), + (types::I32, true) => i64::from(i32::MIN as u32), (types::I64, true) => i64::MIN, _ => unreachable!(), }; @@ -216,9 +215,9 @@ pub(crate) fn type_min_max_value( (types::I16, false) => i64::from(u16::MAX), (types::I32, false) => i64::from(u32::MAX), (types::I64, false) => u64::MAX as i64, - (types::I8, true) => i64::from(i8::MAX), - (types::I16, true) => i64::from(i16::MAX), - (types::I32, true) => i64::from(i32::MAX), + (types::I8, true) => i64::from(i8::MAX as u8), + (types::I16, true) => i64::from(i16::MAX as u16), + (types::I32, true) => i64::from(i32::MAX as u32), (types::I64, true) => i64::MAX, _ => unreachable!(), }; @@ -359,7 +358,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { where T: TypeFoldable> + Copy, { - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index d2b928db7d4df..20f2ee4c76a57 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -1,8 +1,7 @@ use std::sync::{Arc, Condvar, Mutex}; -use rustc_session::Session; - use jobserver::HelperThread; +use rustc_session::Session; // FIXME don't panic when a worker thread panics diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 151674b2d6d8d..1cb6fa0772314 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -1,12 +1,11 @@ //! Handling of `static`s, `const`s and promoted allocations +use cranelift_module::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar}; use rustc_middle::mir::ConstValue; -use cranelift_module::*; - use crate::prelude::*; pub(crate) struct ConstantCx { @@ -64,9 +63,9 @@ pub(crate) fn codegen_tls_ref<'tcx>( pub(crate) fn eval_mir_constant<'tcx>( fx: &FunctionCx<'_, '_, 'tcx>, - constant: &Constant<'tcx>, + constant: &ConstOperand<'tcx>, ) -> (ConstValue<'tcx>, Ty<'tcx>) { - let cv = fx.monomorphize(constant.literal); + let cv = fx.monomorphize(constant.const_); // This cannot fail because we checked all required_consts in advance. let val = cv .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) @@ -76,7 +75,7 @@ pub(crate) fn eval_mir_constant<'tcx>( pub(crate) fn codegen_constant_operand<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - constant: &Constant<'tcx>, + constant: &ConstOperand<'tcx>, ) -> CValue<'tcx> { let (const_val, ty) = eval_mir_constant(fx, constant); codegen_const_value(fx, const_val, ty) @@ -101,7 +100,7 @@ pub(crate) fn codegen_const_value<'tcx>( if fx.clif_type(layout.ty).is_some() { return CValue::const_val(fx, layout, int); } else { - let raw_val = int.to_bits(int.size()).unwrap(); + let raw_val = int.size().truncate(int.to_bits(int.size()).unwrap()); let val = match int.size().bytes() { 1 => fx.bcx.ins().iconst(types::I8, raw_val as i64), 2 => fx.bcx.ins().iconst(types::I16, raw_val as i64), @@ -187,8 +186,7 @@ pub(crate) fn codegen_const_value<'tcx>( ConstValue::Slice { data, meta } => { let alloc_id = fx.tcx.reserve_and_set_memory_alloc(data); let ptr = pointer_for_allocation(fx, alloc_id).get_addr(fx); - // FIXME: the `try_from` here can actually fail, e.g. for very long ZST slices. - let len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(meta).unwrap()); + let len = fx.bcx.ins().iconst(fx.pointer_type, meta as i64); CValue::by_val_pair(ptr, len, layout) } } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs index c4a5627e662f1..81b819a554647 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs @@ -1,10 +1,9 @@ //! Write the debuginfo into an object file. use cranelift_object::ObjectProduct; -use rustc_data_structures::fx::FxHashMap; - use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; +use rustc_data_structures::fx::FxHashMap; use super::object::WriteDebugInfo; use super::DebugContext; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index b19b935a0fea6..d00d19f9a80c4 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs @@ -3,20 +3,18 @@ use std::ffi::OsStr; use std::path::{Component, Path}; -use crate::debuginfo::FunctionDebugContext; -use crate::prelude::*; - -use rustc_data_structures::sync::Lrc; -use rustc_span::{ - FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm, -}; - use cranelift_codegen::binemit::CodeOffset; use cranelift_codegen::MachSrcLoc; - use gimli::write::{ Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable, }; +use rustc_data_structures::sync::Lrc; +use rustc_span::{ + FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm, +}; + +use crate::debuginfo::FunctionDebugContext; +use crate::prelude::*; // OPTIMIZATION: It is cheaper to do this in one pass than using `.parent()` and `.file_name()`. fn split_path_dir_and_file(path: &Path) -> (&Path, &OsStr) { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 8a4b1cccf1460..9e78cc259ce10 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -5,11 +5,8 @@ mod line_info; mod object; mod unwind; -use crate::prelude::*; - use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::TargetIsa; - use gimli::write::{ Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList, UnitEntryId, @@ -17,8 +14,9 @@ use gimli::write::{ use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; use indexmap::IndexSet; -pub(crate) use emit::{DebugReloc, DebugRelocName}; -pub(crate) use unwind::UnwindContext; +pub(crate) use self::emit::{DebugReloc, DebugRelocName}; +pub(crate) use self::unwind::UnwindContext; +use crate::prelude::*; pub(crate) fn producer() -> String { format!( diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs index 9dc9b2cf9f8ad..f1840a7bf7303 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs @@ -1,12 +1,9 @@ -use rustc_data_structures::fx::FxHashMap; - use cranelift_module::FuncId; use cranelift_object::ObjectProduct; - +use gimli::SectionId; use object::write::{Relocation, StandardSegment}; use object::{RelocationEncoding, SectionKind}; - -use gimli::SectionId; +use rustc_data_structures::fx::FxHashMap; use crate::debuginfo::{DebugReloc, DebugRelocName}; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index 493359c743f11..35278e6fb29d3 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -1,15 +1,13 @@ //! Unwind info generation (`.eh_frame`) -use crate::prelude::*; - use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa}; - use cranelift_object::ObjectProduct; use gimli::write::{Address, CieId, EhFrame, FrameTable, Section}; use gimli::RunTimeEndian; use super::object::WriteDebugInfo; +use crate::prelude::*; pub(crate) struct UnwindContext { endian: RunTimeEndian, diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 3e93830951c5c..cc2f5d7271460 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use std::sync::Arc; use std::thread::JoinHandle; +use cranelift_object::{ObjectBuilder, ObjectModule}; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::profiling::SelfProfilerRef; @@ -17,8 +18,6 @@ use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{DebugInfo, OutputFilenames, OutputType}; use rustc_session::Session; -use cranelift_object::{ObjectBuilder, ObjectModule}; - use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 1c606494f383e..6ee65d12c73e9 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -6,13 +6,12 @@ use std::ffi::CString; use std::os::raw::{c_char, c_int}; use std::sync::{mpsc, Mutex, OnceLock}; +use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; use rustc_span::Symbol; -use cranelift_jit::{JITBuilder, JITModule}; - use crate::{prelude::*, BackendConfig}; use crate::{CodegenCx, CodegenMode}; diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index baadd7a9e812b..ebd9b728d90b5 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -9,16 +9,22 @@ use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::{InlineAsmOperand, ItemId}; use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_target::asm::InlineAsmArch; use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir().item(item_id); if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { - if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { - global_asm.push_str("\n.intel_syntax noprefix\n"); - } else { - global_asm.push_str("\n.att_syntax\n"); + let is_x86 = + matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); + + if is_x86 { + if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { + global_asm.push_str("\n.intel_syntax noprefix\n"); + } else { + global_asm.push_str("\n.att_syntax\n"); + } } for piece in asm.template { match *piece { @@ -65,7 +71,11 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } } - global_asm.push_str("\n.att_syntax\n\n"); + + global_asm.push('\n'); + if is_x86 { + global_asm.push_str(".att_syntax\n\n"); + } } else { bug!("Expected GlobalAsm found {:?}", item); } @@ -115,11 +125,12 @@ pub(crate) fn compile_global_asm( } // Remove all LLVM style comments - let global_asm = global_asm + let mut global_asm = global_asm .lines() .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line }) .collect::>() .join("\n"); + global_asm.push('\n'); let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index eba90949b5e5f..dd2127d554dd2 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -1,13 +1,14 @@ //! Codegen of `asm!` invocations. -use crate::prelude::*; - use std::fmt::Write; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::InlineAsmOperand; use rustc_span::sym; use rustc_target::asm::*; +use target_lexicon::BinaryFormat; + +use crate::prelude::*; enum CInlineAsmOperand<'tcx> { In { @@ -43,7 +44,9 @@ pub(crate) fn codegen_inline_asm<'tcx>( ) { // FIXME add .eh_frame unwind info directives - if !template.is_empty() { + if !template.is_empty() + && (cfg!(not(feature = "inline_asm")) || fx.tcx.sess.target.is_like_windows) + { // Used by panic_abort if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { fx.bcx.ins().trap(TrapCode::User(1)); @@ -252,8 +255,8 @@ pub(crate) fn codegen_inline_asm<'tcx>( CInlineAsmOperand::Const { value } } InlineAsmOperand::SymFn { ref value } => { - let literal = fx.monomorphize(value.literal); - if let ty::FnDef(def_id, args) = *literal.ty().kind() { + let const_ = fx.monomorphize(value.const_); + if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( fx.tcx, ty::ParamEnv::reveal_all(), @@ -589,11 +592,29 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } fn generate_asm_wrapper(&self, asm_name: &str) -> String { + let binary_format = crate::target_triple(self.tcx.sess).binary_format; + let mut generated_asm = String::new(); - writeln!(generated_asm, ".globl {}", asm_name).unwrap(); - writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); - writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); - writeln!(generated_asm, "{}:", asm_name).unwrap(); + match binary_format { + BinaryFormat::Elf => { + writeln!(generated_asm, ".globl {}", asm_name).unwrap(); + writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); + writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); + writeln!(generated_asm, "{}:", asm_name).unwrap(); + } + BinaryFormat::Macho => { + writeln!(generated_asm, ".globl _{}", asm_name).unwrap(); + writeln!(generated_asm, "_{}:", asm_name).unwrap(); + } + BinaryFormat::Coff => { + writeln!(generated_asm, ".globl {}", asm_name).unwrap(); + writeln!(generated_asm, "{}:", asm_name).unwrap(); + } + _ => self + .tcx + .sess + .fatal(format!("Unsupported binary format for inline asm: {binary_format:?}")), + } let is_x86 = matches!(self.arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); @@ -690,8 +711,19 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { if is_x86 { generated_asm.push_str(".att_syntax\n"); } - writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); - generated_asm.push_str(".text\n"); + + match binary_format { + BinaryFormat::Elf => { + writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); + generated_asm.push_str(".text\n"); + } + BinaryFormat::Macho | BinaryFormat::Coff => {} + _ => self + .tcx + .sess + .fatal(format!("Unsupported binary format for inline asm: {binary_format:?}")), + } + generated_asm.push_str("\n\n"); generated_asm @@ -699,25 +731,19 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { fn prologue(generated_asm: &mut String, arch: InlineAsmArch) { match arch { - InlineAsmArch::X86 => { - generated_asm.push_str(" push ebp\n"); - generated_asm.push_str(" mov ebp,[esp+8]\n"); - } InlineAsmArch::X86_64 => { generated_asm.push_str(" push rbp\n"); - generated_asm.push_str(" mov rbp,rdi\n"); - } - InlineAsmArch::RiscV32 => { - generated_asm.push_str(" addi sp, sp, -8\n"); - generated_asm.push_str(" sw ra, 4(sp)\n"); - generated_asm.push_str(" sw s0, 0(sp)\n"); - generated_asm.push_str(" mv s0, a0\n"); - } - InlineAsmArch::RiscV64 => { - generated_asm.push_str(" addi sp, sp, -16\n"); - generated_asm.push_str(" sd ra, 8(sp)\n"); - generated_asm.push_str(" sd s0, 0(sp)\n"); - generated_asm.push_str(" mv s0, a0\n"); + generated_asm.push_str(" mov rbp,rsp\n"); + generated_asm.push_str(" push rbx\n"); // rbx is callee saved + // rbx is reserved by LLVM for the "base pointer", so rustc doesn't allow using it + generated_asm.push_str(" mov rbx,rdi\n"); + } + InlineAsmArch::AArch64 => { + generated_asm.push_str(" stp fp, lr, [sp, #-32]!\n"); + generated_asm.push_str(" mov fp, sp\n"); + generated_asm.push_str(" str x19, [sp, #24]\n"); // x19 is callee saved + // x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it + generated_asm.push_str(" mov x19, x0\n"); } _ => unimplemented!("prologue for {:?}", arch), } @@ -725,24 +751,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) { match arch { - InlineAsmArch::X86 => { - generated_asm.push_str(" pop ebp\n"); - generated_asm.push_str(" ret\n"); - } InlineAsmArch::X86_64 => { + generated_asm.push_str(" pop rbx\n"); generated_asm.push_str(" pop rbp\n"); generated_asm.push_str(" ret\n"); } - InlineAsmArch::RiscV32 => { - generated_asm.push_str(" lw s0, 0(sp)\n"); - generated_asm.push_str(" lw ra, 4(sp)\n"); - generated_asm.push_str(" addi sp, sp, 8\n"); - generated_asm.push_str(" ret\n"); - } - InlineAsmArch::RiscV64 => { - generated_asm.push_str(" ld s0, 0(sp)\n"); - generated_asm.push_str(" ld ra, 8(sp)\n"); - generated_asm.push_str(" addi sp, sp, 16\n"); + InlineAsmArch::AArch64 => { + generated_asm.push_str(" ldr x19, [sp, #24]\n"); + generated_asm.push_str(" ldp fp, lr, [sp], #32\n"); generated_asm.push_str(" ret\n"); } _ => unimplemented!("epilogue for {:?}", arch), @@ -751,11 +767,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) { match arch { - InlineAsmArch::X86 | InlineAsmArch::X86_64 => { + InlineAsmArch::X86_64 => { generated_asm.push_str(" ud2\n"); } - InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { - generated_asm.push_str(" ebreak\n"); + InlineAsmArch::AArch64 => { + generated_asm.push_str(" brk #0x1"); } _ => unimplemented!("epilogue_noreturn for {:?}", arch), } @@ -768,25 +784,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { offset: Size, ) { match arch { - InlineAsmArch::X86 => { - write!(generated_asm, " mov [ebp+0x{:x}], ", offset.bytes()).unwrap(); - reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); - generated_asm.push('\n'); - } InlineAsmArch::X86_64 => { - write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap(); + write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap(); reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); generated_asm.push('\n'); } - InlineAsmArch::RiscV32 => { - generated_asm.push_str(" sw "); - reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); - writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); - } - InlineAsmArch::RiscV64 => { - generated_asm.push_str(" sd "); - reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); - writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + InlineAsmArch::AArch64 => { + generated_asm.push_str(" str "); + reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } _ => unimplemented!("save_register for {:?}", arch), } @@ -799,25 +805,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { offset: Size, ) { match arch { - InlineAsmArch::X86 => { - generated_asm.push_str(" mov "); - reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); - writeln!(generated_asm, ", [ebp+0x{:x}]", offset.bytes()).unwrap(); - } InlineAsmArch::X86_64 => { generated_asm.push_str(" mov "); reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); - writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap(); - } - InlineAsmArch::RiscV32 => { - generated_asm.push_str(" lw "); - reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); - writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + writeln!(generated_asm, ", [rbx+0x{:x}]", offset.bytes()).unwrap(); } - InlineAsmArch::RiscV64 => { - generated_asm.push_str(" ld "); - reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); - writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + InlineAsmArch::AArch64 => { + generated_asm.push_str(" ldr "); + reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } _ => unimplemented!("restore_register for {:?}", arch), } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index 63b5402f2b6d9..c169476099806 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -1,10 +1,10 @@ //! Emulate LLVM intrinsics +use rustc_middle::ty::GenericArgsRef; + use crate::intrinsics::*; use crate::prelude::*; -use rustc_middle::ty::GenericArgsRef; - pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs index c20a9915930eb..0c211a06dc4a7 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs @@ -1,10 +1,10 @@ //! Emulate AArch64 LLVM intrinsics +use rustc_middle::ty::GenericArgsRef; + use crate::intrinsics::*; use crate::prelude::*; -use rustc_middle::ty::GenericArgsRef; - pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, @@ -156,6 +156,41 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + // FIXME generalize vector types + "llvm.aarch64.neon.tbl1.v16i8" => { + intrinsic_args!(fx, args => (t, idx); intrinsic); + + let zero = fx.bcx.ins().iconst(types::I8, 0); + for i in 0..16 { + let idx_lane = idx.value_lane(fx, i).load_scalar(fx); + let is_zero = + fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, idx_lane, 16); + let t_idx = fx.bcx.ins().uextend(fx.pointer_type, idx_lane); + let t_lane = t.value_lane_dyn(fx, t_idx).load_scalar(fx); + let res = fx.bcx.ins().select(is_zero, zero, t_lane); + ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); + } + } + + // FIXME generalize vector types + "llvm.aarch64.neon.umaxp.v16i8" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + // FIXME add helper for horizontal pairwise operations + for i in 0..8 { + let lane1 = a.value_lane(fx, i * 2).load_scalar(fx); + let lane2 = a.value_lane(fx, i * 2 + 1).load_scalar(fx); + let res = fx.bcx.ins().umax(lane1, lane2); + ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); + } + for i in 0..8 { + let lane1 = b.value_lane(fx, i * 2).load_scalar(fx); + let lane2 = b.value_lane(fx, i * 2 + 1).load_scalar(fx); + let res = fx.bcx.ins().umax(lane1, lane2); + ret.place_lane(fx, 8 + i).to_ptr().store(fx, res, MemFlags::trusted()); + } + } + /* _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v") || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v") diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index e62de6b61477d..0c9a94e1c231f 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -1,10 +1,10 @@ //! Emulate x86 LLVM intrinsics +use rustc_middle::ty::GenericArgsRef; + use crate::intrinsics::*; use crate::prelude::*; -use rustc_middle::ty::GenericArgsRef; - pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, @@ -74,8 +74,10 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( }; let x = codegen_operand(fx, x); let y = codegen_operand(fx, y); - let kind = crate::constant::mir_operand_get_const_val(fx, kind) - .expect("llvm.x86.sse2.cmp.* kind not const"); + let kind = match kind { + Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, + Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"), + }; let flt_cc = match kind .try_to_bits(Size::from_bytes(1)) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 36e9ba9c7f8e4..e94091e6a25eb 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -18,17 +18,16 @@ mod llvm_aarch64; mod llvm_x86; mod simd; -pub(crate) use cpuid::codegen_cpuid_call; -pub(crate) use llvm::codegen_llvm_intrinsic_call; - +use cranelift_codegen::ir::AtomicRmwOp; use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; use rustc_span::symbol::{kw, sym, Symbol}; +pub(crate) use self::cpuid::codegen_cpuid_call; +pub(crate) use self::llvm::codegen_llvm_intrinsic_call; use crate::prelude::*; -use cranelift_codegen::ir::AtomicRmwOp; fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! { bug!("wrong number of args for intrinsic {}", intrinsic); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index c64a4008996d5..ea137c4ca1e8c 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -21,7 +21,7 @@ fn report_simd_type_validation_error( pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, - _args: GenericArgsRef<'tcx>, + generic_args: GenericArgsRef<'tcx>, args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, target: BasicBlock, @@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } + // simd_shuffle_generic(x: T, y: T) -> U + sym::simd_shuffle_generic => { + let [x, y] = args else { + bug!("wrong number of args for intrinsic {intrinsic}"); + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + + if !x.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); + return; + } + + let idx = generic_args[2] + .expect_const() + .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(span)) + .unwrap() + .unwrap_branch(); + + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + + assert_eq!(lane_ty, ret_lane_ty); + assert_eq!(idx.len() as u64, ret_lane_count); + + let total_len = lane_count * 2; + + let indexes = + idx.iter().map(|idx| idx.unwrap_leaf().try_to_u32().unwrap()).collect::>(); + + for &idx in &indexes { + assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len); + } + + for (out_idx, in_idx) in indexes.into_iter().enumerate() { + let in_lane = if u64::from(in_idx) < lane_count { + x.value_lane(fx, in_idx.into()) + } else { + y.value_lane(fx, u64::from(in_idx) - lane_count) + }; + let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); + out_lane.write_cvalue(fx, in_lane); + } + } + // simd_shuffle(x: T, y: T, idx: I) -> U sym::simd_shuffle => { let (x, y, idx) = match args { @@ -168,8 +216,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = crate::constant::mir_operand_get_const_val(fx, idx) - .expect("simd_shuffle idx not const"); + let idx_const = match idx { + Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, + Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"), + }; let idx_bytes = match idx_const { ConstValue::Indirect { alloc_id, offset } => { @@ -295,7 +345,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret.write_cvalue(fx, ret_lane); } - sym::simd_neg => { + sym::simd_neg + | sym::simd_bswap + | sym::simd_bitreverse + | sym::simd_ctlz + | sym::simd_cttz => { intrinsic_args!(fx, args => (a); intrinsic); if !a.layout().ty.is_simd() { @@ -303,16 +357,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; } - simd_for_each_lane( - fx, - a, - ret, - &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { - ty::Int(_) => fx.bcx.ins().ineg(lane), - ty::Float(_) => fx.bcx.ins().fneg(lane), - _ => unreachable!(), - }, - ); + simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| match ( + lane_ty.kind(), + intrinsic, + ) { + (ty::Int(_), sym::simd_neg) => fx.bcx.ins().ineg(lane), + (ty::Float(_), sym::simd_neg) => fx.bcx.ins().fneg(lane), + + (ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8), sym::simd_bswap) => lane, + (ty::Uint(_) | ty::Int(_), sym::simd_bswap) => fx.bcx.ins().bswap(lane), + (ty::Uint(_) | ty::Int(_), sym::simd_bitreverse) => fx.bcx.ins().bitrev(lane), + (ty::Uint(_) | ty::Int(_), sym::simd_ctlz) => fx.bcx.ins().clz(lane), + (ty::Uint(_) | ty::Int(_), sym::simd_cttz) => fx.bcx.ins().ctz(lane), + + _ => unreachable!(), + }); } sym::simd_add diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index d01ded8abaa52..522fe7e425b90 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -29,6 +29,8 @@ use std::any::Any; use std::cell::{Cell, RefCell}; use std::sync::Arc; +use cranelift_codegen::isa::TargetIsa; +use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::profiling::SelfProfilerRef; @@ -39,9 +41,6 @@ use rustc_session::config::OutputFilenames; use rustc_session::Session; use rustc_span::Symbol; -use cranelift_codegen::isa::TargetIsa; -use cranelift_codegen::settings::{self, Configurable}; - pub use crate::config::*; use crate::prelude::*; @@ -76,22 +75,6 @@ mod value_and_place; mod vtable; mod prelude { - pub(crate) use rustc_span::{FileNameDisplayPreference, Span}; - - pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; - pub(crate) use rustc_middle::bug; - pub(crate) use rustc_middle::mir::{self, *}; - pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout}; - pub(crate) use rustc_middle::ty::{ - self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, - TypeFoldable, TypeVisitableExt, UintTy, - }; - pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT}; - - pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; - - pub(crate) use rustc_index::Idx; - pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; pub(crate) use cranelift_codegen::ir::function::Function; pub(crate) use cranelift_codegen::ir::types; @@ -103,6 +86,18 @@ mod prelude { pub(crate) use cranelift_codegen::Context; pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module}; + pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; + pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; + pub(crate) use rustc_index::Idx; + pub(crate) use rustc_middle::bug; + pub(crate) use rustc_middle::mir::{self, *}; + pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout}; + pub(crate) use rustc_middle::ty::{ + self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, + TypeFoldable, TypeVisitableExt, UintTy, + }; + pub(crate) use rustc_span::{FileNameDisplayPreference, Span}; + pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT}; pub(crate) use crate::abi::*; pub(crate) use crate::base::{codegen_operand, codegen_place}; @@ -263,9 +258,9 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc "elf_gd", diff --git a/compiler/rustc_codegen_cranelift/src/pointer.rs b/compiler/rustc_codegen_cranelift/src/pointer.rs index b60e56720ed5e..11ac6b9467834 100644 --- a/compiler/rustc_codegen_cranelift/src/pointer.rs +++ b/compiler/rustc_codegen_cranelift/src/pointer.rs @@ -1,11 +1,10 @@ //! Defines [`Pointer`] which is used to improve the quality of the generated clif ir for pointer //! operations. -use crate::prelude::*; - +use cranelift_codegen::ir::immediates::Offset32; use rustc_target::abi::Align; -use cranelift_codegen::ir::immediates::Offset32; +use crate::prelude::*; /// A pointer pointing either to a certain address, a certain stack slot or nothing. #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 0ead50c34eac4..da84e54a91636 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -63,8 +63,8 @@ use cranelift_codegen::{ ir::entities::AnyEntity, write::{FuncWriter, PlainWriter}, }; - use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -80,15 +80,17 @@ impl CommentWriter { pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { let enabled = should_write_ir(tcx); let global_comments = if enabled { - vec![ - format!("symbol {}", tcx.symbol_name(instance).name), - format!("instance {:?}", instance), - format!( - "abi {:?}", - RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) - ), - String::new(), - ] + with_no_trimmed_paths!({ + vec![ + format!("symbol {}", tcx.symbol_name(instance).name), + format!("instance {:?}", instance), + format!( + "abi {:?}", + RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) + ), + String::new(), + ] + }) } else { vec![] }; diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index ff95141ce90fb..3a6a6c9e3f508 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -1,11 +1,10 @@ //! Definition of [`CValue`] and [`CPlace`] -use crate::prelude::*; - -use rustc_middle::ty::FnSig; - use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; +use rustc_middle::ty::FnSig; + +use crate::prelude::*; fn codegen_field<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -310,7 +309,8 @@ impl<'tcx> CValue<'tcx> { fx.bcx.ins().iconcat(lsb, msb) } ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Ref(..) | ty::RawPtr(..) => { - fx.bcx.ins().iconst(clif_ty, const_val.to_bits(layout.size).unwrap() as i64) + let raw_val = const_val.size().truncate(const_val.to_bits(layout.size).unwrap()); + fx.bcx.ins().iconst(clif_ty, raw_val as i64) } ty::Float(FloatTy::F32) => { fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(const_val).unwrap())) @@ -674,7 +674,9 @@ impl<'tcx> CPlace<'tcx> { } } - pub(crate) fn place_opaque_cast( + /// Used for `ProjectionElem::Subtype`, `ty` has to be monomorphized before + /// passed on. + pub(crate) fn place_transmute_type( self, fx: &mut FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 308cb04cac3d5..ecc293aee237b 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1420,7 +1420,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.cx } - fn do_not_inline(&mut self, _llret: RValue<'gcc>) { + fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) { // FIXME(bjorn3): implement } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 697ae015fed9a..ce7e31682f101 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -80,7 +80,7 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMes use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::query::Providers; +use rustc_middle::util::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh index 592997b8ab9da..b462e5d156b23 100755 --- a/compiler/rustc_codegen_gcc/test.sh +++ b/compiler/rustc_codegen_gcc/test.sh @@ -214,7 +214,7 @@ function setup_rustc() { rm config.toml || true cat > config.toml < bool { match crate_type { - CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true, - CrateType::Rlib | CrateType::ProcMacro => false, + CrateType::Executable + | CrateType::Dylib + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::ProcMacro => true, + CrateType::Rlib => false, } } @@ -87,6 +91,11 @@ fn prepare_lto( diag_handler.emit_err(LtoDylib); return Err(FatalError); } + } else if *crate_type == CrateType::ProcMacro { + if !cgcx.opts.unstable_opts.dylib_lto { + diag_handler.emit_err(LtoProcMacro); + return Err(FatalError); + } } } diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs new file mode 100644 index 0000000000000..36484c3c3fc44 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -0,0 +1,103 @@ +use std::{ + ffi::{c_char, CStr}, + marker::PhantomData, + ops::Deref, + ptr::NonNull, +}; + +use rustc_data_structures::small_c_str::SmallCStr; + +use crate::{errors::LlvmError, llvm}; + +/// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions. +/// Not cloneable as there is no clone function for llvm::TargetMachine. +#[repr(transparent)] +pub struct OwnedTargetMachine { + tm_unique: NonNull, + phantom: PhantomData, +} + +impl OwnedTargetMachine { + pub fn new( + triple: &CStr, + cpu: &CStr, + features: &CStr, + abi: &CStr, + model: llvm::CodeModel, + reloc: llvm::RelocModel, + level: llvm::CodeGenOptLevel, + use_soft_fp: bool, + function_sections: bool, + data_sections: bool, + unique_section_names: bool, + trap_unreachable: bool, + singletree: bool, + asm_comments: bool, + emit_stack_size_section: bool, + relax_elf_relocations: bool, + use_init_array: bool, + split_dwarf_file: &CStr, + output_obj_file: &CStr, + debug_info_compression: &CStr, + force_emulated_tls: bool, + args_cstr_buff: &[u8], + ) -> Result> { + assert!(args_cstr_buff.len() > 0); + assert!( + *args_cstr_buff.last().unwrap() == 0, + "The last character must be a null terminator." + ); + + // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data + let tm_ptr = unsafe { + llvm::LLVMRustCreateTargetMachine( + triple.as_ptr(), + cpu.as_ptr(), + features.as_ptr(), + abi.as_ptr(), + model, + reloc, + level, + use_soft_fp, + function_sections, + data_sections, + unique_section_names, + trap_unreachable, + singletree, + asm_comments, + emit_stack_size_section, + relax_elf_relocations, + use_init_array, + split_dwarf_file.as_ptr(), + output_obj_file.as_ptr(), + debug_info_compression.as_ptr(), + force_emulated_tls, + args_cstr_buff.as_ptr() as *const c_char, + args_cstr_buff.len(), + ) + }; + + NonNull::new(tm_ptr) + .map(|tm_unique| Self { tm_unique, phantom: PhantomData }) + .ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) }) + } +} + +impl Deref for OwnedTargetMachine { + type Target = llvm::TargetMachine; + + fn deref(&self) -> &Self::Target { + // SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine + unsafe { self.tm_unique.as_ref() } + } +} + +impl Drop for OwnedTargetMachine { + fn drop(&mut self) { + // SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine + // OwnedTargetMachine is not copyable so there is no double free or use after free + unsafe { + llvm::LLVMRustDisposeTargetMachine(self.tm_unique.as_mut()); + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 1f394a7335c7e..c778a6e017fac 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1,4 +1,5 @@ use crate::back::lto::ThinBuffer; +use crate::back::owned_target_machine::OwnedTargetMachine; use crate::back::profiling::{ selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler, }; @@ -98,8 +99,8 @@ pub fn write_output_file<'ll>( } } -pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine { - let config = TargetMachineFactoryConfig { split_dwarf_file: None }; +pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine { + let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None }; // Can't use query system here quite yet because this function is invoked before the query // system/tcx is set up. let features = llvm_util::global_llvm_features(sess, false); @@ -107,7 +108,7 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm: .unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise()) } -pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { +pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { tcx.output_filenames(()).split_dwarf_path( tcx.sess.split_debuginfo(), @@ -117,7 +118,11 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll } else { None }; - let config = TargetMachineFactoryConfig { split_dwarf_file }; + + let output_obj_file = + Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name))); + let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; + target_machine_factory( &tcx.sess, tcx.backend_optimization_level(()), @@ -255,38 +260,38 @@ pub fn target_machine_factory( let debuginfo_compression = SmallCStr::new(&debuginfo_compression); Arc::new(move |config: TargetMachineFactoryConfig| { - let split_dwarf_file = - path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; - let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap(); - - let tm = unsafe { - llvm::LLVMRustCreateTargetMachine( - triple.as_ptr(), - cpu.as_ptr(), - features.as_ptr(), - abi.as_ptr(), - code_model, - reloc_model, - opt_level, - use_softfp, - ffunction_sections, - fdata_sections, - funique_section_names, - trap_unreachable, - singlethread, - asm_comments, - emit_stack_size_section, - relax_elf_relocations, - use_init_array, - split_dwarf_file.as_ptr(), - debuginfo_compression.as_ptr(), - force_emulated_tls, - args_cstr_buff.as_ptr() as *const c_char, - args_cstr_buff.len(), - ) + let path_to_cstring_helper = |path: Option| -> CString { + let path = path_mapping.map_prefix(path.unwrap_or_default()).0; + CString::new(path.to_str().unwrap()).unwrap() }; - tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() }) + let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file); + let output_obj_file = path_to_cstring_helper(config.output_obj_file); + + OwnedTargetMachine::new( + &triple, + &cpu, + &features, + &abi, + code_model, + reloc_model, + opt_level, + use_softfp, + ffunction_sections, + fdata_sections, + funique_section_names, + trap_unreachable, + singlethread, + asm_comments, + emit_stack_size_section, + relax_elf_relocations, + use_init_array, + &split_dwarf_file, + &output_obj_file, + &debuginfo_compression, + force_emulated_tls, + &args_cstr_buff, + ) }) } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ac6d8f84142e7..4f9b86ec20a7b 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -3,6 +3,7 @@ use crate::attributes; use crate::common::Funclet; use crate::context::CodegenCx; use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -1225,9 +1226,16 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn do_not_inline(&mut self, llret: &'ll Value) { - let noinline = llvm::AttributeKind::NoInline.create_attr(self.llcx); - attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[noinline]); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) { + if llvm_util::get_version() < (17, 0, 2) { + // Work around https://github.com/llvm/llvm-project/issues/66984. + let noinline = llvm::AttributeKind::NoInline.create_attr(self.llcx); + attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[noinline]); + } else { + // Cleanup is always the cold path. + let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx); + attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]); + } } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 8e8290279abd2..b4b2ab1e1f8a9 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -160,9 +160,9 @@ pub unsafe fn create_module<'ll>( // Ensure the data-layout values hardcoded remain the defaults. if sess.target.is_builtin { + // tm is disposed by its drop impl let tm = crate::back::write::create_informational_target_machine(tcx.sess); - llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); - llvm::LLVMRustDisposeTargetMachine(tm); + llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm); let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod); let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes()) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 7a82d05ce9ea2..763186a58bf9f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, MappedExpressionIndex}; +use rustc_middle::mir::coverage::{CounterId, ExpressionId, Operand}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -30,11 +30,8 @@ pub struct Counter { } impl Counter { - /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the - /// `id` is not used. - pub fn zero() -> Self { - Self { kind: CounterKind::Zero, id: 0 } - } + /// A `Counter` of kind `Zero`. For this counter kind, the `id` is not used. + pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 }; /// Constructs a new `Counter` of kind `CounterValueReference`. pub fn counter_value_reference(counter_id: CounterId) -> Self { @@ -42,20 +39,16 @@ impl Counter { } /// Constructs a new `Counter` of kind `Expression`. - pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { - Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } - } - - /// Returns true if the `Counter` kind is `Zero`. - pub fn is_zero(&self) -> bool { - matches!(self.kind, CounterKind::Zero) + pub(crate) fn expression(expression_id: ExpressionId) -> Self { + Self { kind: CounterKind::Expression, id: expression_id.as_u32() } } - /// An explicitly-named function to get the ID value, making it more obvious - /// that the stored value is now 0-based. - pub fn zero_based_id(&self) -> u32 { - debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); - self.id + pub(crate) fn from_operand(operand: Operand) -> Self { + match operand { + Operand::Zero => Self::ZERO, + Operand::Counter(id) => Self::counter_value_reference(id), + Operand::Expression(id) => Self::expression(id), + } } } @@ -81,6 +74,11 @@ pub struct CounterExpression { } impl CounterExpression { + /// The dummy expression `(0 - 0)` has a representation of all zeroes, + /// making it marginally more efficient to initialize than `(0 + 0)`. + pub(crate) const DUMMY: Self = + Self { lhs: Counter::ZERO, kind: ExprKind::Subtract, rhs: Counter::ZERO }; + pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self { Self { kind, lhs, rhs } } @@ -172,7 +170,7 @@ impl CounterMappingRegion { ) -> Self { Self { counter, - false_counter: Counter::zero(), + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, @@ -220,8 +218,8 @@ impl CounterMappingRegion { end_col: u32, ) -> Self { Self { - counter: Counter::zero(), - false_counter: Counter::zero(), + counter: Counter::ZERO, + false_counter: Counter::ZERO, file_id, expanded_file_id, start_line, @@ -243,8 +241,8 @@ impl CounterMappingRegion { end_col: u32, ) -> Self { Self { - counter: Counter::zero(), - false_counter: Counter::zero(), + counter: Counter::ZERO, + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, @@ -268,7 +266,7 @@ impl CounterMappingRegion { ) -> Self { Self { counter, - false_counter: Counter::zero(), + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index f1e68af25d406..55f43aa534173 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,10 +1,8 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; -use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::bug; -use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, ExpressionId, MappedExpressionIndex, Op, Operand, -}; +use rustc_data_structures::fx::FxIndexSet; +use rustc_index::IndexVec; +use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; @@ -13,7 +11,7 @@ pub struct Expression { lhs: Operand, op: Op, rhs: Operand, - region: Option, + code_regions: Vec, } /// Collects all of the coverage regions associated with (a) injected counters, (b) counter @@ -32,7 +30,7 @@ pub struct FunctionCoverage<'tcx> { instance: Instance<'tcx>, source_hash: u64, is_used: bool, - counters: IndexVec>, + counters: IndexVec>>, expressions: IndexVec>, unreachable_regions: Vec, } @@ -79,28 +77,40 @@ impl<'tcx> FunctionCoverage<'tcx> { } } - /// Adds a code region to be counted by an injected counter intrinsic. - pub fn add_counter(&mut self, id: CounterId, region: CodeRegion) { - if let Some(previous_region) = self.counters[id].replace(region.clone()) { - assert_eq!(previous_region, region, "add_counter: code region for id changed"); + /// Adds code regions to be counted by an injected counter intrinsic. + #[instrument(level = "debug", skip(self))] + pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) { + if code_regions.is_empty() { + return; + } + + let slot = &mut self.counters[id]; + match slot { + None => *slot = Some(code_regions.to_owned()), + // If this counter ID slot has already been filled, it should + // contain identical information. + Some(ref previous_regions) => assert_eq!( + previous_regions, code_regions, + "add_counter: code regions for id changed" + ), } } + /// Adds information about a coverage expression, along with zero or more + /// code regions mapped to that expression. + /// /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity /// between operands that are counter IDs and operands that are expression IDs. - pub fn add_counter_expression( + #[instrument(level = "debug", skip(self))] + pub(crate) fn add_counter_expression( &mut self, expression_id: ExpressionId, lhs: Operand, op: Op, rhs: Operand, - region: Option, + code_regions: &[CodeRegion], ) { - debug!( - "add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}", - expression_id, lhs, op, rhs, region - ); debug_assert!( expression_id.as_usize() < self.expressions.len(), "expression_id {} is out of range for expressions.len() = {} @@ -109,23 +119,77 @@ impl<'tcx> FunctionCoverage<'tcx> { self.expressions.len(), self, ); - if let Some(previous_expression) = self.expressions[expression_id].replace(Expression { - lhs, - op, - rhs, - region: region.clone(), - }) { - assert_eq!( - previous_expression, - Expression { lhs, op, rhs, region }, + + let expression = Expression { lhs, op, rhs, code_regions: code_regions.to_owned() }; + let slot = &mut self.expressions[expression_id]; + match slot { + None => *slot = Some(expression), + // If this expression ID slot has already been filled, it should + // contain identical information. + Some(ref previous_expression) => assert_eq!( + previous_expression, &expression, "add_counter_expression: expression for id changed" - ); + ), } } - /// Add a region that will be marked as "unreachable", with a constant "zero counter". - pub fn add_unreachable_region(&mut self, region: CodeRegion) { - self.unreachable_regions.push(region) + /// Adds regions that will be marked as "unreachable", with a constant "zero counter". + #[instrument(level = "debug", skip(self))] + pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) { + assert!(!code_regions.is_empty(), "unreachable regions always have code regions"); + self.unreachable_regions.extend_from_slice(code_regions); + } + + /// Perform some simplifications to make the final coverage mappings + /// slightly smaller. + /// + /// This method mainly exists to preserve the simplifications that were + /// already being performed by the Rust-side expression renumbering, so that + /// the resulting coverage mappings don't get worse. + pub(crate) fn simplify_expressions(&mut self) { + // The set of expressions that either were optimized out entirely, or + // have zero as both of their operands, and will therefore always have + // a value of zero. Other expressions that refer to these as operands + // can have those operands replaced with `Operand::Zero`. + let mut zero_expressions = FxIndexSet::default(); + + // For each expression, perform simplifications based on lower-numbered + // expressions, and then update the set of always-zero expressions if + // necessary. + // (By construction, expressions can only refer to other expressions + // that have lower IDs, so one simplification pass is sufficient.) + for (id, maybe_expression) in self.expressions.iter_enumerated_mut() { + let Some(expression) = maybe_expression else { + // If an expression is missing, it must have been optimized away, + // so any operand that refers to it can be replaced with zero. + zero_expressions.insert(id); + continue; + }; + + // If an operand refers to an expression that is always zero, then + // that operand can be replaced with `Operand::Zero`. + let maybe_set_operand_to_zero = |operand: &mut Operand| match &*operand { + Operand::Expression(id) if zero_expressions.contains(id) => { + *operand = Operand::Zero; + } + _ => (), + }; + maybe_set_operand_to_zero(&mut expression.lhs); + maybe_set_operand_to_zero(&mut expression.rhs); + + // Coverage counter values cannot be negative, so if an expression + // involves subtraction from zero, assume that its RHS must also be zero. + // (Do this after simplifications that could set the LHS to zero.) + if let Expression { lhs: Operand::Zero, op: Op::Subtract, .. } = expression { + expression.rhs = Operand::Zero; + } + + // After the above simplifications, if both operands are zero, then + // we know that this expression is always zero too. + if let Expression { lhs: Operand::Zero, rhs: Operand::Zero, .. } = expression { + zero_expressions.insert(id); + } + } } /// Return the source hash, generated from the HIR node structure, and used to indicate whether @@ -146,8 +210,14 @@ impl<'tcx> FunctionCoverage<'tcx> { self.instance ); + let counter_expressions = self.counter_expressions(); + // Expression IDs are indices into `self.expressions`, and on the LLVM + // side they will be treated as indices into `counter_expressions`, so + // the two vectors should correspond 1:1. + assert_eq!(self.expressions.len(), counter_expressions.len()); + let counter_regions = self.counter_regions(); - let (counter_expressions, expression_regions) = self.expressions_with_regions(); + let expression_regions = self.expression_regions(); let unreachable_regions = self.unreachable_regions(); let counter_regions = @@ -156,156 +226,69 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn counter_regions(&self) -> impl Iterator { - self.counters.iter_enumerated().filter_map(|(index, entry)| { - // Option::map() will return None to filter out missing counters. This may happen - // if, for example, a MIR-instrumented counter is removed during an optimization. - entry.as_ref().map(|region| (Counter::counter_value_reference(index), region)) - }) + self.counters + .iter_enumerated() + // Filter out counter IDs that we never saw during MIR traversal. + // This can happen if a counter was optimized out by MIR transforms + // (and replaced with `CoverageKind::Unreachable` instead). + .filter_map(|(id, maybe_code_regions)| Some((id, maybe_code_regions.as_ref()?))) + .flat_map(|(id, code_regions)| { + let counter = Counter::counter_value_reference(id); + code_regions.iter().map(move |region| (counter, region)) + }) } - fn expressions_with_regions( - &self, - ) -> (Vec, impl Iterator) { - let mut counter_expressions = Vec::with_capacity(self.expressions.len()); - let mut expression_regions = Vec::with_capacity(self.expressions.len()); - let mut new_indexes = IndexVec::from_elem_n(None, self.expressions.len()); - - // This closure converts any `Expression` operand (`lhs` or `rhs` of the `Op::Add` or - // `Op::Subtract` operation) into its native `llvm::coverage::Counter::CounterKind` type - // and value. - // - // Expressions will be returned from this function in a sequential vector (array) of - // `CounterExpression`, so the expression IDs must be mapped from their original, - // potentially sparse set of indexes. - // - // An `Expression` as an operand will have already been encountered as an `Expression` with - // operands, so its new_index will already have been generated (as a 1-up index value). - // (If an `Expression` as an operand does not have a corresponding new_index, it was - // probably optimized out, after the expression was injected into the MIR, so it will - // get a `CounterKind::Zero` instead.) - // - // In other words, an `Expression`s at any given index can include other expressions as - // operands, but expression operands can only come from the subset of expressions having - // `expression_index`s lower than the referencing `Expression`. Therefore, it is - // reasonable to look up the new index of an expression operand while the `new_indexes` - // vector is only complete up to the current `ExpressionIndex`. - type NewIndexes = IndexSlice>; - let id_to_counter = |new_indexes: &NewIndexes, operand: Operand| match operand { - Operand::Zero => Some(Counter::zero()), - Operand::Counter(id) => Some(Counter::counter_value_reference(id)), - Operand::Expression(id) => { - self.expressions - .get(id) - .expect("expression id is out of range") - .as_ref() - // If an expression was optimized out, assume it would have produced a count - // of zero. This ensures that expressions dependent on optimized-out - // expressions are still valid. - .map_or(Some(Counter::zero()), |_| new_indexes[id].map(Counter::expression)) - } - }; - - for (original_index, expression) in - self.expressions.iter_enumerated().filter_map(|(original_index, entry)| { - // Option::map() will return None to filter out missing expressions. This may happen - // if, for example, a MIR-instrumented expression is removed during an optimization. - entry.as_ref().map(|expression| (original_index, expression)) - }) - { - let optional_region = &expression.region; - let Expression { lhs, op, rhs, .. } = *expression; + /// Convert this function's coverage expression data into a form that can be + /// passed through FFI to LLVM. + fn counter_expressions(&self) -> Vec { + // We know that LLVM will optimize out any unused expressions before + // producing the final coverage map, so there's no need to do the same + // thing on the Rust side unless we're confident we can do much better. + // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.) - if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs) - .map(|lhs_counter| { - id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter)) - }) - { - if lhs_counter.is_zero() && op.is_subtract() { - // The left side of a subtraction was probably optimized out. As an example, - // a branch condition might be evaluated as a constant expression, and the - // branch could be removed, dropping unused counters in the process. - // - // Since counters are unsigned, we must assume the result of the expression - // can be no more and no less than zero. An expression known to evaluate to zero - // does not need to be added to the coverage map. - // - // Coverage test `loops_branches.rs` includes multiple variations of branches - // based on constant conditional (literal `true` or `false`), and demonstrates - // that the expected counts are still correct. - debug!( - "Expression subtracts from zero (assume unreachable): \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, lhs, op, rhs, optional_region, - ); - rhs_counter = Counter::zero(); + self.expressions + .iter() + .map(|expression| match expression { + None => { + // This expression ID was allocated, but we never saw the + // actual expression, so it must have been optimized out. + // Replace it with a dummy expression, and let LLVM take + // care of omitting it from the expression list. + CounterExpression::DUMMY } - debug_assert!( - lhs_counter.is_zero() - // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` - || ((lhs_counter.zero_based_id() as usize) - <= usize::max(self.counters.len(), self.expressions.len())), - "lhs id={} > both counters.len()={} and expressions.len()={} - ({:?} {:?} {:?})", - lhs_counter.zero_based_id(), - self.counters.len(), - self.expressions.len(), - lhs_counter, - op, - rhs_counter, - ); - - debug_assert!( - rhs_counter.is_zero() - // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` - || ((rhs_counter.zero_based_id() as usize) - <= usize::max(self.counters.len(), self.expressions.len())), - "rhs id={} > both counters.len()={} and expressions.len()={} - ({:?} {:?} {:?})", - rhs_counter.zero_based_id(), - self.counters.len(), - self.expressions.len(), - lhs_counter, - op, - rhs_counter, - ); - - // Both operands exist. `Expression` operands exist in `self.expressions` and have - // been assigned a `new_index`. - let mapped_expression_index = - MappedExpressionIndex::from(counter_expressions.len()); - let expression = CounterExpression::new( - lhs_counter, - match op { - Op::Add => ExprKind::Add, - Op::Subtract => ExprKind::Subtract, - }, - rhs_counter, - ); - debug!( - "Adding expression {:?} = {:?}, region: {:?}", - mapped_expression_index, expression, optional_region - ); - counter_expressions.push(expression); - new_indexes[original_index] = Some(mapped_expression_index); - if let Some(region) = optional_region { - expression_regions.push((Counter::expression(mapped_expression_index), region)); + &Some(Expression { lhs, op, rhs, .. }) => { + // Convert the operands and operator as normal. + CounterExpression::new( + Counter::from_operand(lhs), + match op { + Op::Add => ExprKind::Add, + Op::Subtract => ExprKind::Subtract, + }, + Counter::from_operand(rhs), + ) } - } else { - bug!( - "expression has one or more missing operands \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, - lhs, - op, - rhs, - optional_region, - ); - } - } - (counter_expressions, expression_regions.into_iter()) + }) + .collect::>() + } + + fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> { + // Find all of the expression IDs that weren't optimized out AND have + // one or more attached code regions, and return the corresponding + // mappings as counter/region pairs. + self.expressions + .iter_enumerated() + .filter_map(|(id, maybe_expression)| { + let code_regions = &maybe_expression.as_ref()?.code_regions; + Some((id, code_regions)) + }) + .flat_map(|(id, code_regions)| { + let counter = Counter::expression(id); + code_regions.iter().map(move |code_region| (counter, code_region)) + }) + .collect::>() } fn unreachable_regions(&self) -> impl Iterator { - self.unreachable_regions.iter().map(|region| (Counter::zero(), region)) + self.unreachable_regions.iter().map(|region| (Counter::ZERO, region)) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 8ba7a11abe5ca..d4e775256985c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -60,8 +60,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // Encode coverage mappings and generate function records let mut function_data = Vec::new(); - for (instance, function_coverage) in function_coverage_map { + for (instance, mut function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); + function_coverage.simplify_expressions(); + let function_coverage = function_coverage; + let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); let is_used = function_coverage.is_used(); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c70cb670e96fb..dd2ce9b525b77 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -89,9 +89,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// `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 + /// them. Since the function is never called, all of its `CodeRegion`s can be /// added as `unreachable_region`s. fn define_unused_fn(&self, def_id: DefId) { let instance = declare_unused_fn(self, def_id); @@ -110,25 +108,15 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); - let Coverage { kind, code_region } = coverage.clone(); - match kind { + let Coverage { kind, code_regions } = coverage; + match *kind { CoverageKind::Counter { function_source_hash, id } => { debug!( "ensuring function source hash is set for instance={:?}; function_source_hash={}", instance, function_source_hash, ); func_coverage.set_function_source_hash(function_source_hash); - - 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. - debug!( - "adding counter to coverage_map: instance={:?}, id={:?}, region={:?}", - instance, id, code_region, - ); - func_coverage.add_counter(id, code_region); - } + func_coverage.add_counter(id, code_regions); // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, // as that needs an exclusive borrow. drop(coverage_map); @@ -146,20 +134,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { bx.instrprof_increment(fn_name, hash, num_counters, index); } CoverageKind::Expression { id, lhs, op, rhs } => { - debug!( - "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; region: {:?}", - instance, id, lhs, op, rhs, code_region, - ); - func_coverage.add_counter_expression(id, lhs, op, rhs, code_region); + func_coverage.add_counter_expression(id, lhs, op, rhs, code_regions); } CoverageKind::Unreachable => { - let code_region = - code_region.expect("unreachable regions always have code regions"); - debug!( - "adding unreachable code to coverage_map: instance={:?}, at {:?}", - instance, code_region, - ); - func_coverage.add_unreachable_region(code_region); + func_coverage.add_unreachable_regions(code_regions); } } } @@ -227,14 +205,9 @@ fn add_unused_function_coverage<'tcx>( let tcx = cx.tcx; let mut function_coverage = FunctionCoverage::unused(tcx, instance); - for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() { - if index == 0 { - // Insert at least one real counter so the LLVM CoverageMappingReader will find expected - // definitions. - function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone()); - } else { - function_coverage.add_unreachable_region(code_region.clone()); - } + for &code_region in tcx.covered_code_regions(def_id) { + let code_region = std::slice::from_ref(code_region); + function_coverage.add_unreachable_regions(code_region); } if let Some(coverage_context) = cx.coverage_context() { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 5ca2942ac4eda..aff764f0224c9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -90,7 +90,7 @@ fn make_mir_scope<'ll, 'tcx>( Some((callee, _)) => { // FIXME(eddyb) this would be `self.monomorphize(&callee)` // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. - let callee = cx.tcx.subst_and_normalize_erasing_regions( + let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(callee), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ed938761694dc..11874898a5adb 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -335,12 +335,20 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( // This is actually a function pointer, so wrap it in pointer DI. let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); + let (size, align) = match fn_ty.kind() { + ty::FnDef(..) => (0, 1), + ty::FnPtr(..) => ( + cx.tcx.data_layout.pointer_size.bits(), + cx.tcx.data_layout.pointer_align.abi.bits() as u32, + ), + _ => unreachable!(), + }; let di_node = unsafe { llvm::LLVMRustDIBuilderCreatePointerType( DIB(cx), fn_di_node, - cx.tcx.data_layout.pointer_size.bits(), - cx.tcx.data_layout.pointer_align.abi.bits() as u32, + size, + align, 0, // Ignore DWARF address space. name.as_ptr().cast(), name.len(), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c862acdc7def4..30cc9ea9b8258 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -529,7 +529,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) { // If the method does *not* belong to a trait, proceed if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { - let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), cx.tcx.type_of(impl_def_id), diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 264c273ba3072..665d195790c2d 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -138,6 +138,10 @@ pub(crate) struct LtoDisallowed; #[diag(codegen_llvm_lto_dylib)] pub(crate) struct LtoDylib; +#[derive(Diagnostic)] +#[diag(codegen_llvm_lto_proc_macro)] +pub(crate) struct LtoProcMacro; + #[derive(Diagnostic)] #[diag(codegen_llvm_lto_bitcode_from_rlib)] pub(crate) struct LtoBitcodeFromRlib { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 9289c37d76352..a97b803fc645b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; @@ -376,7 +376,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { - match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { + match generic_simd_intrinsic( + self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span, + ) { Ok(llval) => llval, Err(()) => return, } @@ -911,6 +913,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, + fn_args: GenericArgsRef<'tcx>, args: &[OperandRef<'tcx, &'ll Value>], ret_ty: Ty<'tcx>, llret_ty: &'ll Type, @@ -1030,6 +1033,56 @@ fn generic_simd_intrinsic<'ll, 'tcx>( )); } + if name == sym::simd_shuffle_generic { + let idx = fn_args[2] + .expect_const() + .eval(tcx, ty::ParamEnv::reveal_all(), Some(span)) + .unwrap() + .unwrap_branch(); + let n = idx.len() as u64; + + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( + out_len == n, + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } + ); + require!( + in_elem == out_ty, + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + ); + + let total_len = in_len * 2; + + let indices: Option> = idx + .iter() + .enumerate() + .map(|(arg_idx, val)| { + let idx = val.unwrap_leaf().try_to_i32().unwrap(); + if idx >= i32::try_from(total_len).unwrap() { + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds { + span, + name, + arg_idx: arg_idx as u64, + total_len: total_len.into(), + }); + None + } else { + Some(bx.const_i32(idx)) + } + }) + .collect(); + let Some(indices) = indices else { + return Ok(bx.const_null(llret_ty)); + }; + + return Ok(bx.shuffle_vector( + args[0].immediate(), + args[1].immediate(), + bx.const_vector(&indices), + )); + } + if name == sym::simd_shuffle { // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index ac199624e347b..59d1ea05d8a16 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -22,6 +22,7 @@ extern crate rustc_macros; #[macro_use] extern crate tracing; +use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use errors::ParseTargetMachineConfig; @@ -39,8 +40,8 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, Subd use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_middle::util::Providers; use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; @@ -52,6 +53,7 @@ use std::io::Write; mod back { pub mod archive; pub mod lto; + pub mod owned_target_machine; mod profiling; pub mod write; } @@ -162,7 +164,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend { impl WriteBackendMethods for LlvmCodegenBackend { type Module = ModuleLlvm; type ModuleBuffer = back::lto::ModuleBuffer; - type TargetMachine = &'static mut llvm::TargetMachine; + type TargetMachine = OwnedTargetMachine; type TargetMachineError = crate::errors::LlvmError<'static>; type ThinData = back::lto::ThinData; type ThinBuffer = back::lto::ThinBuffer; @@ -401,7 +403,9 @@ impl CodegenBackend for LlvmCodegenBackend { pub struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, - tm: &'static mut llvm::TargetMachine, + + // independent from llcx and llmod_raw, resources get disposed by drop impl + tm: OwnedTargetMachine, } unsafe impl Send for ModuleLlvm {} @@ -453,7 +457,6 @@ impl ModuleLlvm { impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { - llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 2ebfdae39e805..a038b3af03dd6 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2112,6 +2112,8 @@ extern "C" { ); pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; + + // This function makes copies of pointed to data, so the data's lifetime may end after this function returns pub fn LLVMRustCreateTargetMachine( Triple: *const c_char, CPU: *const c_char, @@ -2131,13 +2133,14 @@ extern "C" { RelaxELFRelocations: bool, UseInitArray: bool, SplitDwarfFile: *const c_char, + OutputObjFile: *const c_char, DebugInfoCompression: *const c_char, ForceEmulatedTls: bool, ArgsCstrBuff: *const c_char, ArgsCstrBuffLen: usize, - ) -> Option<&'static mut TargetMachine>; + ) -> *mut TargetMachine; - pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); + pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine); pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, M: &'a Module, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a76c9c9b7356c..7c8ef67ffd10e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -303,7 +303,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { // check that all features in a given smallvec are enabled for llvm_feature in to_llvm_features(sess, feature) { let cstr = SmallCStr::new(llvm_feature); - if !unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } { + if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { return false; } } @@ -422,14 +422,14 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut dyn PrintBackendInfo, sess } unsafe { llvm::LLVMRustPrintTargetCPUs( - tm, + &tm, cpu_cstring.as_ptr(), callback, &mut out as *mut &mut dyn PrintBackendInfo as *mut c_void, ); } } - PrintKind::TargetFeatures => print_target_features(out, sess, tm), + PrintKind::TargetFeatures => print_target_features(out, sess, &tm), _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 8db6195d931f0..06b7703672fe8 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -112,7 +112,7 @@ impl<'ll> CodegenCx<'ll, '_> { } } - /// Return a LLVM type that has at most the required alignment, + /// Return an LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type { let unit = Integer::approximate_align(self, align); diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index d0a078505d2d4..6648266733614 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -46,8 +46,6 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` .note = an unsuffixed integer value, e.g., `1`, is expected -codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` @@ -170,8 +168,6 @@ codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple time codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} -codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc - codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} .note = {$output} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a7ac728c59b02..464424409c7c2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -365,15 +365,9 @@ fn link_rlib<'a>( // loaded from the libraries found here and then encode that into the // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { - let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else { + let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else { continue; }; - if whole_archive == Some(true) - && flavor == RlibFlavor::Normal - && !codegen_results.crate_info.feature_packed_bundled_libs - { - sess.emit_err(errors::IncompatibleLinkingModifiers); - } if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename { let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); let src = read(path).map_err(|e| sess.emit_fatal(errors::ReadFileError {message: e }))?; @@ -2970,31 +2964,22 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result { @@ -82,12 +81,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> OsS // Mac doesn't appear to support $ORIGIN let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" }; - let cwd = env::current_dir().unwrap(); - let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or_else(|_| cwd.join(lib)); - lib.pop(); // strip filename - let mut output = cwd.join(&config.out_filename); - output.pop(); // strip filename - let output = fs::canonicalize(&output).unwrap_or(output); + // Strip filenames + let lib = lib.parent().unwrap(); + let output = config.out_filename.parent().unwrap(); + let lib = try_canonicalize(lib).unwrap(); + let output = try_canonicalize(output).unwrap(); let relative = path_relative_from(&lib, &output) .unwrap_or_else(|| panic!("couldn't create relative path from {output:?} to {lib:?}")); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 5b869bed0a0dc..9cd4394108a4a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -11,10 +11,10 @@ use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, }; use rustc_middle::query::LocalCrate; -use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, SymbolName, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; +use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; use rustc_target::spec::SanitizerSet; @@ -457,11 +457,9 @@ pub fn provide(providers: &mut Providers) { providers.is_unreachable_local_definition = is_unreachable_local_definition_provider; providers.upstream_drop_glue_for = upstream_drop_glue_for_provider; providers.wasm_import_module_map = wasm_import_module_map; -} - -pub fn provide_extern(providers: &mut ExternProviders) { - providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern; - providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider; + providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern; + providers.extern_queries.upstream_monomorphizations_for = + upstream_monomorphizations_for_provider; } fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 3bf98c46dea7b..f192747c8abaa 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -286,6 +286,10 @@ pub struct TargetMachineFactoryConfig { /// so the path to the dwarf object has to be provided when we create the target machine. /// This can be ignored by backends which do not need it for their Split DWARF support. pub split_dwarf_file: Option, + + /// The name of the output object file. Used for setting OutputFilenames in target options + /// so that LLVM can emit the CodeView S_OBJNAME record in pdb files + pub output_obj_file: Option, } impl TargetMachineFactoryConfig { @@ -302,7 +306,10 @@ impl TargetMachineFactoryConfig { } else { None }; - TargetMachineFactoryConfig { split_dwarf_file } + + let output_obj_file = + Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name))); + TargetMachineFactoryConfig { split_dwarf_file, output_obj_file } } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index cd19885faa0e1..1e4ea73a1724f 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -181,7 +181,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( old_info } } - (_, &ty::Dynamic(ref data, _, _)) => meth::get_vtable(cx, source, data.principal()), + (_, ty::Dynamic(data, _, _)) => meth::get_vtable(cx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } @@ -420,9 +420,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( rust_main_def_id: DefId, entry_type: EntryFnType, ) -> Bx::Function { - // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, - // depending on whether the target needs `argc` and `argv` to be passed in. - let llfty = if cx.sess().target.main_needs_argc_argv { + // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or + // `usize efi_main(void *handle, void *system_table)` depending on the target. + let llfty = if cx.sess().target.os.contains("uefi") { + cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize()) + } else if cx.sess().target.main_needs_argc_argv { cx.type_func(&[cx.type_int(), cx.type_ptr()], cx.type_int()) } else { cx.type_func(&[], cx.type_int()) @@ -485,8 +487,12 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; let result = bx.call(start_ty, None, None, start_fn, &args, None); - let cast = bx.intcast(result, cx.type_int(), true); - bx.ret(cast); + if cx.sess().target.os.contains("uefi") { + bx.ret(result); + } else { + let cast = bx.intcast(result, cx.type_int(), true); + bx.ret(cast); + } llfn } @@ -497,7 +503,17 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, bx: &mut Bx, ) -> (Bx::Value, Bx::Value) { - if cx.sess().target.main_needs_argc_argv { + if cx.sess().target.os.contains("uefi") { + // Params for UEFI + let param_handle = bx.get_param(0); + let param_system_table = bx.get_param(1); + let arg_argc = bx.const_int(cx.type_isize(), 2); + let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE); + bx.store(param_handle, arg_argv, Align::ONE); + let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]); + bx.store(param_system_table, arg_argv_el1, Align::ONE); + (arg_argc, arg_argv) + } else if cx.sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function let param_argc = bx.get_param(0); let param_argv = bx.get_param(1); @@ -841,7 +857,6 @@ impl CrateInfo { dependency_formats: tcx.dependency_formats(()).clone(), windows_subsystem, natvis_debugger_visualizers: Default::default(), - feature_packed_bundled_libs: tcx.features().packed_bundled_libs, }; let crates = tcx.crates(()); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index e21148a4de146..989df448a319e 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -426,7 +426,6 @@ fn push_debuginfo_type_name<'tcx>( | ty::Placeholder(..) | ty::Alias(..) | ty::Bound(..) - | ty::GeneratorWitnessMIR(..) | ty::GeneratorWitness(..) => { bug!( "debuginfo: Trying to create type name for \ @@ -660,12 +659,12 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S } _ => match ct.ty().kind() { ty::Int(ity) => { - let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty()); + let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; write!(output, "{val}") } ty::Uint(_) => { - let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty()); + let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); write!(output, "{val}") } ty::Bool => { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index bfd572a2eeafe..39b2fa37fbf87 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -107,10 +107,6 @@ pub struct CreateTempDir { pub error: Error, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_incompatible_linking_modifiers)] -pub struct IncompatibleLinkingModifiers; - #[derive(Diagnostic)] #[diag(codegen_ssa_add_native_library)] pub struct AddNativeLibrary { @@ -493,10 +489,6 @@ pub struct RlibArchiveBuildFailure { pub error: Error, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_option_gcc_only)] -pub struct OptionGccOnly; - #[derive(Diagnostic)] pub enum ExtractBundledLibsError<'a> { #[diag(codegen_ssa_extract_bundled_libs_open_file)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 7bed3fa615034..f6186a290f81f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -31,7 +31,7 @@ use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_middle::query::{ExternProviders, Providers}; +use rustc_middle::util::Providers; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; @@ -164,7 +164,6 @@ pub struct CrateInfo { pub dependency_formats: Lrc, pub windows_subsystem: Option, pub natvis_debugger_visualizers: BTreeSet, - pub feature_packed_bundled_libs: bool, // unstable feature flag. } #[derive(Encodable, Decodable)] @@ -190,10 +189,6 @@ pub fn provide(providers: &mut Providers) { crate::codegen_attrs::provide(providers); } -pub fn provide_extern(providers: &mut ExternProviders) { - crate::back::symbol_export::provide_extern(providers); -} - /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc` /// uses for the object files it generates. pub fn looks_like_rust_object_file(filename: &str) -> bool { diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 7fda2d5fadf7b..62e997e5cfa48 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -8,7 +8,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{self, Location, TerminatorKind}; +use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( @@ -67,21 +67,6 @@ enum LocalKind { SSA(DefLocation), } -#[derive(Copy, Clone, PartialEq, Eq)] -enum DefLocation { - Argument, - Body(Location), -} - -impl DefLocation { - fn dominates(self, location: Location, dominators: &Dominators) -> bool { - match self { - DefLocation::Argument => true, - DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators), - } - } -} - struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { fx: &'mir FunctionCx<'a, 'tcx, Bx>, dominators: &'mir Dominators, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b738a49bf1196..a0cb97d51a01f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -213,7 +213,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { self.funclet(fx), ); if fx.mir[self.bb].is_cleanup { - bx.do_not_inline(invokeret); + bx.apply_attrs_to_cleanup_callsite(invokeret); } if let Some((ret_dest, target)) = destination { @@ -228,11 +228,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } else { let llret = bx.call(fn_ty, fn_attrs, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { - // Cleanup is always the cold path. Don't inline - // drop glue. Also, when there is a deeply-nested - // struct, there are "symmetry" issues that cause - // exponential inlining - see issue #41696. - bx.do_not_inline(llret); + bx.apply_attrs_to_cleanup_callsite(llret); } if let Some((ret_dest, target)) = destination { @@ -1098,8 +1094,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { InlineAsmOperandRef::Const { string } } mir::InlineAsmOperand::SymFn { ref value } => { - let literal = self.monomorphize(value.literal); - if let ty::FnDef(def_id, args) = *literal.ty().kind() { + let const_ = self.monomorphize(value.const_); + if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), ty::ParamEnv::reveal_all(), @@ -1627,7 +1623,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ty = bx.fn_decl_backend_type(&fn_abi); let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); - bx.do_not_inline(llret); + bx.apply_attrs_to_cleanup_callsite(llret); bx.unreachable(); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 7fec4047a95c8..558f64fffc263 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -13,37 +13,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant_to_operand( &self, bx: &mut Bx, - constant: &mir::Constant<'tcx>, + constant: &mir::ConstOperand<'tcx>, ) -> OperandRef<'tcx, Bx::Value> { let val = self.eval_mir_constant(constant); let ty = self.monomorphize(constant.ty()); OperandRef::from_const(bx, val, ty) } - pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> mir::ConstValue<'tcx> { - self.monomorphize(constant.literal) + pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::ConstValue<'tcx> { + // `MirUsedCollector` visited all constants before codegen began, so if we got here there + // can be no more constants that fail to evaluate. + self.monomorphize(constant.const_) .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span)) .expect("erroneous constant not captured by required_consts") } /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition - /// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to + /// that the given `constant` is an `Const::Unevaluated` and must be convertible to /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip. /// /// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees! pub fn eval_unevaluated_mir_constant_to_valtree( &self, - constant: &mir::Constant<'tcx>, + constant: &mir::ConstOperand<'tcx>, ) -> Result>, ErrorHandled> { - let uv = match self.monomorphize(constant.literal) { - mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(), - mir::ConstantKind::Ty(c) => match c.kind() { + let uv = match self.monomorphize(constant.const_) { + mir::Const::Unevaluated(uv, _) => uv.shrink(), + mir::Const::Ty(c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to old-style // simd_shuffle (passing as argument instead of as a generic param). rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)), other => span_bug!(constant.span, "{other:#?}"), }, - // We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate + // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate // a constant and write that value back into `Operand`s. This could happen, but is unlikely. // Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care // around intrinsics. For an issue to happen here, it would require a macro expanding to a @@ -65,7 +67,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn simd_shuffle_indices( &mut self, bx: &Bx, - constant: &mir::Constant<'tcx>, + constant: &mir::ConstOperand<'tcx>, ) -> (Bx::Value, Ty<'tcx>) { let ty = self.monomorphize(constant.ty()); let val = self diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d156011476317..0dc30d21c5b40 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -158,8 +158,7 @@ fn calculate_debuginfo_offset< L: DebugInfoOffsetLocation<'tcx, Bx>, >( bx: &mut Bx, - local: mir::Local, - var: &PerLocalVarDebugInfo<'tcx, Bx::DIVariable>, + projection: &[mir::PlaceElem<'tcx>], base: L, ) -> DebugInfoOffset { let mut direct_offset = Size::ZERO; @@ -167,7 +166,7 @@ fn calculate_debuginfo_offset< let mut indirect_offsets = vec![]; let mut place = base; - for elem in &var.projection[..] { + for elem in projection { match *elem { mir::ProjectionElem::Deref => { indirect_offsets.push(Size::ZERO); @@ -188,11 +187,7 @@ fn calculate_debuginfo_offset< } => { let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset); let FieldsShape::Array { stride, count: _ } = place.layout().fields else { - span_bug!( - var.source_info.span, - "ConstantIndex on non-array type {:?}", - place.layout() - ) + bug!("ConstantIndex on non-array type {:?}", place.layout()) }; *offset += stride * index; place = place.project_constant_index(bx, index); @@ -200,11 +195,7 @@ fn calculate_debuginfo_offset< _ => { // Sanity check for `can_use_in_debuginfo`. debug_assert!(!elem.can_use_in_debuginfo()); - span_bug!( - var.source_info.span, - "unsupported var debuginfo place `{:?}`", - mir::Place { local, projection: var.projection }, - ) + bug!("unsupported var debuginfo projection `{:?}`", projection) } } } @@ -407,7 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = - calculate_debuginfo_offset(bx, local, &var, base.layout); + calculate_debuginfo_offset(bx, &var.projection, base.layout); // When targeting MSVC, create extra allocas for arguments instead of pointing multiple // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records @@ -425,7 +416,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if should_create_individual_allocas { let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } = - calculate_debuginfo_offset(bx, local, &var, base); + calculate_debuginfo_offset(bx, &var.projection, base); // Create a variable which will be a pointer to the actual value let ptr_ty = Ty::new_ptr( @@ -532,23 +523,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fragment = if let Some(ref fragment) = var.composite { let var_layout = self.cx.layout_of(var_ty); - let mut fragment_start = Size::ZERO; - let mut fragment_layout = var_layout; - - for elem in &fragment.projection { - match *elem { - mir::ProjectionElem::Field(field, _) => { - let i = field.index(); - fragment_start += fragment_layout.fields.offset(i); - fragment_layout = fragment_layout.field(self.cx, i); - } - _ => span_bug!( - var.source_info.span, - "unsupported fragment projection `{:?}`", - elem, - ), - } - } + let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } = + calculate_debuginfo_offset(bx, &fragment.projection, var_layout); + debug_assert!(indirect_offsets.is_empty()); if fragment_layout.size == Size::ZERO { // Fragment is a ZST, so does not represent anything. Avoid generating anything @@ -559,7 +536,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // DWARF is concerned, it's not really a fragment. None } else { - Some(fragment_start..fragment_start + fragment_layout.size) + Some(direct_offset..direct_offset + fragment_layout.size) } } else { None diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1e905a7c78e47..d0b799e087b2a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { T: Copy + TypeFoldable>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), @@ -209,18 +209,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( caller_location: None, }; - fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); + // It may seem like we should iterate over `required_consts` to ensure they all successfully + // evaluate; however, the `MirUsedCollector` already did that during the collection phase of + // monomorphization so we don't have to do it again. - // Rust post-monomorphization checks; we later rely on them. - if let Err(err) = - mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) - { - err.emit_err(cx.tcx()); - // This IR shouldn't ever be emitted, but let's try to guard against any of this code - // ever running. - start_bx.abort(); - return; - } + fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); let memory_locals = analyze::non_ssa_locals(&fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 9205acc527e53..0ab2b7ecd9c80 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -135,15 +135,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { assert_eq!(alloc_align, layout.align.abi); let read_scalar = |start, size, s: abi::Scalar, ty| { - let val = alloc - .0 - .read_scalar( - bx, - alloc_range(start, size), - /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), - ) - .unwrap(); - bx.scalar_to_backend(val, s, ty) + match alloc.0.read_scalar( + bx, + alloc_range(start, size), + /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), + ) { + Ok(val) => bx.scalar_to_backend(val, s, ty), + Err(_) => bx.const_poison(ty), + } }; // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point. @@ -156,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(Size::ZERO, size, s, bx.type_ptr()); + let val = read_scalar(offset, size, s, bx.backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout } } Abi::ScalarPair( @@ -164,10 +163,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b @ abi::Scalar::Initialized { .. }, ) => { let (a_size, b_size) = (a.size(bx), b.size(bx)); - let b_offset = a_size.align_to(b.align(bx).abi); + let b_offset = (offset + a_size).align_to(b.align(bx).abi); assert!(b_offset.bytes() > 0); let a_val = read_scalar( - Size::ZERO, + offset, a_size, a, bx.scalar_pair_element_backend_type(layout, 0, true), diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index a9ecbdc5f35ed..eb590a45a63f2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -463,7 +463,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::Field(ref field, _) => { cg_base.project_field(bx, field.index()) } - mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty), + mir::ProjectionElem::OpaqueCast(ty) => { + bug!("encountered OpaqueCast({ty}) in codegen") + } + mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)), mir::ProjectionElem::Index(index) => { let index = &mir::Operand::Copy(mir::Place::from(index)); let index = self.codegen_operand(bx, index); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 0a02ca6b317c2..ac8123bc1be91 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -11,9 +11,9 @@ use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::util::Providers; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, cstore::MetadataLoaderDyn, @@ -85,7 +85,6 @@ pub trait CodegenBackend { } fn provide(&self, _providers: &mut Providers) {} - fn provide_extern(&self, _providers: &mut ExternProviders) {} fn codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 853c6934c2c24..aa411f002a0c6 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -332,5 +332,5 @@ pub trait BuilderMethods<'a, 'tcx>: ) -> Self::Value; fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - fn do_not_inline(&mut self, llret: Self::Value); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index dc3dbd9d81949..b1fde8e4d8638 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -30,7 +30,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type; fn element_type(&self, ty: Self::Type) -> Self::Type; - /// Returns the number of elements in `self` if it is a LLVM vector type. + /// Returns the number of elements in `self` if it is an LLVM vector type. fn vector_length(&self, ty: Self::Type) -> usize; fn float_width(&self, ty: Self::Type) -> usize; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f16aea6f34b75..865e01d0aee0f 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -3,7 +3,7 @@ use rustc_hir::{LangItem, CRATE_HIR_ID}; use rustc_middle::mir; use rustc_middle::mir::interpret::PointerArithmetic; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::INVALID_ALIGNMENT; use std::borrow::Borrow; use std::hash::Hash; @@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { ) -> InterpResult<'tcx, Option>> { let def_id = instance.def_id(); - if Some(def_id) == self.tcx.lang_items().panic_display() + if self.tcx.has_attr(def_id, sym::rustc_const_panic_str) || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { let args = self.copy_fn_args(args)?; @@ -596,7 +596,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _bin_op: mir::BinOp, _left: &ImmTy<'tcx>, _right: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx>, bool)> { throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time"); } diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 886d7972a1529..bcbe996be7d88 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -4,6 +4,7 @@ use crate::errors::MaxNumNodesInConstErr; use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar}; use rustc_middle::mir; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; @@ -86,17 +87,17 @@ pub(crate) fn eval_to_valtree<'tcx>( #[instrument(skip(tcx), level = "debug")] pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>( - tcx: TyCtxt<'tcx>, + tcx: TyCtxtAt<'tcx>, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, ) -> Option> { let param_env = ty::ParamEnv::reveal_all(); - let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); + let ecx = mk_eval_cx(tcx.tcx, tcx.span, param_env, CanAccessStatics::No); 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 ty.kind() { - ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op), + ty::Array(_, len) => (len.eval_target_usize(tcx.tcx, param_env) as usize, None, op), ty::Adt(def, _) if def.variants().is_empty() => { return None; } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 2fba7455cb2f1..7436ea6ae5756 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -152,7 +152,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) | ty::Generator(..) - | ty::GeneratorWitness(..) |ty::GeneratorWitnessMIR(..)=> Err(ValTreeCreationError::NonSupportedType), + | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType), } } @@ -280,7 +280,6 @@ pub fn valtree_to_const_value<'tcx>( | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::FnPtr(_) | ty::RawPtr(_) | ty::Str diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index bd897ffaafc4f..b9f88cf635271 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -24,41 +24,44 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { cast_ty: Ty<'tcx>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { + // `cast_ty` will often be the same as `dest.ty`, but not always, since subtyping is still + // possible. + let cast_layout = + if cast_ty == dest.layout.ty { dest.layout } else { self.layout_of(cast_ty)? }; // FIXME: In which cases should we trigger UB when the source is uninit? match cast_kind { CastKind::PointerCoercion(PointerCoercion::Unsize) => { - let cast_ty = self.layout_of(cast_ty)?; - self.unsize_into(src, cast_ty, dest)?; + self.unsize_into(src, cast_layout, dest)?; } CastKind::PointerExposeAddress => { let src = self.read_immediate(src)?; - let res = self.pointer_expose_address_cast(&src, cast_ty)?; - self.write_immediate(res, dest)?; + let res = self.pointer_expose_address_cast(&src, cast_layout)?; + self.write_immediate(*res, dest)?; } CastKind::PointerFromExposedAddress => { let src = self.read_immediate(src)?; - let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?; - self.write_immediate(res, dest)?; + let res = self.pointer_from_exposed_address_cast(&src, cast_layout)?; + self.write_immediate(*res, dest)?; } 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)?; + let res = self.int_to_int_or_float(&src, cast_layout)?; + self.write_immediate(*res, dest)?; } 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)?; + let res = self.float_to_float_or_int(&src, cast_layout)?; + self.write_immediate(*res, dest)?; } CastKind::FnPtrToPtr | CastKind::PtrToPtr => { let src = self.read_immediate(src)?; - let res = self.ptr_to_ptr(&src, cast_ty)?; - self.write_immediate(res, dest)?; + let res = self.ptr_to_ptr(&src, cast_layout)?; + self.write_immediate(*res, dest)?; } CastKind::PointerCoercion( @@ -87,7 +90,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.fn_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } - _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "reify fn pointer on {}", src.layout.ty), } } @@ -98,7 +101,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // No change to value self.write_immediate(*src, dest)?; } - _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty), + _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {}", cast_ty), } } @@ -119,7 +122,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.fn_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } - _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "closure fn pointer on {}", src.layout.ty), } } @@ -140,6 +143,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { CastKind::Transmute => { assert!(src.layout.is_sized()); assert!(dest.layout.is_sized()); + assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely... if src.layout.size != dest.layout.size { let src_bytes = src.layout.size.bytes(); let dest_bytes = dest.layout.size.bytes(); @@ -164,62 +168,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn int_to_int_or_float( &self, src: &ImmTy<'tcx, M::Provenance>, - cast_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Immediate> { + cast_to: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()); - assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()); + assert!(cast_to.ty.is_floating_point() || cast_to.ty.is_integral() || cast_to.ty.is_char()); - Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into()) + Ok(ImmTy::from_scalar( + self.cast_from_int_like(src.to_scalar(), src.layout, cast_to.ty)?, + cast_to, + )) } /// Handles 'FloatToFloat' and 'FloatToInt' casts. pub fn float_to_float_or_int( &self, src: &ImmTy<'tcx, M::Provenance>, - cast_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Immediate> { + cast_to: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_type_ir::sty::TyKind::*; - match src.layout.ty.kind() { + let val = match src.layout.ty.kind() { // Floating point - Float(FloatTy::F32) => { - return Ok(self.cast_from_float(src.to_scalar().to_f32()?, cast_ty).into()); - } - Float(FloatTy::F64) => { - return Ok(self.cast_from_float(src.to_scalar().to_f64()?, cast_ty).into()); - } + Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), + Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), _ => { - bug!("Can't cast 'Float' type into {:?}", cast_ty); + bug!("Can't cast 'Float' type into {}", cast_to.ty); } - } + }; + Ok(ImmTy::from_scalar(val, cast_to)) } /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts. pub fn ptr_to_ptr( &self, src: &ImmTy<'tcx, M::Provenance>, - cast_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Immediate> { + cast_to: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { assert!(src.layout.ty.is_any_ptr()); - assert!(cast_ty.is_unsafe_ptr()); + assert!(cast_to.ty.is_unsafe_ptr()); // Handle casting any ptr to raw ptr (might be a fat ptr). - let dest_layout = self.layout_of(cast_ty)?; - if dest_layout.size == src.layout.size { + if cast_to.size == src.layout.size { // Thin or fat pointer that just hast the ptr kind of target type changed. - return Ok(**src); + return Ok(ImmTy::from_immediate(**src, cast_to)); } else { // Casting the metadata away from a fat ptr. assert_eq!(src.layout.size, 2 * self.pointer_size()); - assert_eq!(dest_layout.size, self.pointer_size()); + assert_eq!(cast_to.size, self.pointer_size()); assert!(src.layout.ty.is_unsafe_ptr()); return match **src { - Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::ScalarPair(data, _) => Ok(ImmTy::from_scalar(data, cast_to)), Immediate::Scalar(..) => span_bug!( self.cur_span(), - "{:?} input to a fat-to-thin cast ({:?} -> {:?})", + "{:?} input to a fat-to-thin cast ({} -> {})", *src, src.layout.ty, - cast_ty + cast_to.ty ), Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), }; @@ -229,10 +232,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn pointer_expose_address_cast( &mut self, src: &ImmTy<'tcx, M::Provenance>, - cast_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Immediate> { + cast_to: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_)); - assert!(cast_ty.is_integral()); + assert!(cast_to.ty.is_integral()); let scalar = src.to_scalar(); let ptr = scalar.to_pointer(self)?; @@ -240,16 +243,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(ptr) => M::expose_ptr(self, ptr)?, Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP. }; - Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) + Ok(ImmTy::from_scalar(self.cast_from_int_like(scalar, src.layout, cast_to.ty)?, cast_to)) } pub fn pointer_from_exposed_address_cast( &self, src: &ImmTy<'tcx, M::Provenance>, - cast_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Immediate> { + cast_to: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { assert!(src.layout.ty.is_integral()); - assert_matches!(cast_ty.kind(), ty::RawPtr(_)); + assert_matches!(cast_to.ty.kind(), ty::RawPtr(_)); // First cast to usize. let scalar = src.to_scalar(); @@ -258,12 +261,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Then turn address into pointer. let ptr = M::ptr_from_addr_cast(&self, addr)?; - Ok(Scalar::from_maybe_pointer(ptr, self).into()) + Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(ptr, self), cast_to)) } /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input /// type (basically everything with a scalar layout) to int/float/char types. - pub fn cast_from_int_like( + fn cast_from_int_like( &self, scalar: Scalar, // input value (there is no ScalarTy so we separate data+layout) src_layout: TyAndLayout<'tcx>, @@ -298,7 +301,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Casts to bool are not permitted by rustc, no need to handle them here. - _ => span_bug!(self.cur_span(), "invalid int to {:?} cast", cast_ty), + _ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty), }) } @@ -331,7 +334,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // float -> f64 Float(FloatTy::F64) => Scalar::from_f64(f.convert(&mut false).value), // That's it. - _ => span_bug!(self.cur_span(), "invalid float to {:?} cast", dest_ty), + _ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty), } } @@ -390,7 +393,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { span_bug!( self.cur_span(), - "invalid pointer unsizing {:?} -> {:?}", + "invalid pointer unsizing {} -> {}", src.layout.ty, cast_ty ) @@ -404,7 +407,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { cast_ty: TyAndLayout<'tcx>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - trace!("Unsizing {:?} of type {} into {:?}", *src, src.layout.ty, cast_ty.ty); + trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(TypeAndMut { ty: c, .. })) | (&ty::RawPtr(TypeAndMut { ty: s, .. }), &ty::RawPtr(TypeAndMut { ty: c, .. })) => { diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 440ee06e7fe70..49e01728ff4b0 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -76,7 +76,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = ImmTy::from_uint(variant_index_relative, tag_layout); - let tag_val = self.binary_op( + let tag_val = self.wrapping_binary_op( mir::BinOp::Add, &variant_index_relative_val, &niche_start_val, @@ -153,19 +153,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Figure out which discriminant and variant this corresponds to. let index = match *tag_encoding { TagEncoding::Direct => { - let scalar = tag_val.to_scalar(); // Generate a specific error if `tag_val` is not an integer. // (`tag_bits` itself is only used for error messages below.) - let tag_bits = scalar + let tag_bits = tag_val + .to_scalar() .try_to_int() .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? .assert_bits(tag_layout.size); // Cast bits from tag layout to discriminant layout. // After the checks we did above, this cannot fail, as // discriminants are int-like. - let discr_val = - self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap(); - let discr_bits = discr_val.assert_bits(discr_layout.size); + let discr_val = self.int_to_int_or_float(&tag_val, discr_layout).unwrap(); + let discr_bits = discr_val.to_scalar().assert_bits(discr_layout.size); // Convert discriminant to variant index, and catch invalid discriminants. let index = match *ty.kind() { ty::Adt(adt, _) => { @@ -208,7 +207,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let tag_val = ImmTy::from_uint(tag_bits, tag_layout); let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = - self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; + self.wrapping_binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; let variant_index_relative = variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size); // Check if this is in the range that indicates an actual discriminant. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cb14e165b5c4b..1c2e8d807f4e6 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance}; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_session::Limit; use rustc_span::Span; @@ -384,7 +384,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. - if util::is_subtype(tcx, param_env, src.ty, dest.ty) { + if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) { // Make sure the layout is equal, too -- just to be safe. Miri really // needs layout equality. For performance reason we skip this check when // the types are equal. Equal types *can* have different layouts when @@ -416,7 +416,7 @@ pub(super) fn from_known_layout<'tcx>( if !mir_assign_valid_types(tcx.tcx, param_env, check_layout, known_layout) { span_bug!( tcx.span, - "expected type differs from actual type.\nexpected: {:?}\nactual: {:?}", + "expected type differs from actual type.\nexpected: {}\nactual: {}", known_layout.ty, check_layout.ty, ); @@ -569,7 +569,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> Result { frame .instance - .try_subst_mir_and_normalize_erasing_regions( + .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, self.param_env, ty::EarlyBinder::bind(value), @@ -712,7 +712,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Foreign(_) => Ok(None), - _ => span_bug!(self.cur_span(), "size_and_align_of::<{:?}> not supported", layout.ty), + _ => span_bug!(self.cur_span(), "size_and_align_of::<{}> not supported", layout.ty), } } #[inline] @@ -750,12 +750,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). if M::POST_MONO_CHECKS { - // `ctfe_query` does some error message decoration that we want to be in effect here. - self.ctfe_query(None, |tcx| { - body.post_mono_checks(*tcx, self.param_env, |c| { - self.subst_from_current_frame_and_normalize_erasing_regions(c) - }) - })?; + for &const_ in &body.required_consts { + let c = + self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?; + c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| { + err.emit_note(*self.tcx); + err + })?; + } } // done @@ -963,7 +965,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -982,7 +983,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`is_very_trivially_sized` applied to unexpected type: {:?}", ty) + bug!("`is_very_trivially_sized` applied to unexpected type: {}", ty) } } } @@ -1055,14 +1056,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } - /// Call a query that can return `ErrorHandled`. If `span` is `Some`, point to that span when an error occurs. + /// Call a query that can return `ErrorHandled`. Should be used for statics and other globals. + /// (`mir::Const`/`ty::Const` have `eval` methods that can be used directly instead.) pub fn ctfe_query( &self, - span: Option, query: impl FnOnce(TyCtxtAt<'tcx>) -> Result, ) -> Result { // Use a precise span for better cycle errors. - query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| { + query(self.tcx.at(self.cur_span())).map_err(|err| { err.emit_note(*self.tcx); err }) @@ -1083,17 +1084,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.param_env }; - let val = self.ctfe_query(None, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?; + let val = self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?; self.raw_const_to_mplace(val) } pub fn eval_mir_constant( &self, - val: &mir::ConstantKind<'tcx>, + val: &mir::Const<'tcx>, span: Option, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let const_val = self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?; + let const_val = val.eval(*self.tcx, self.param_env, span).map_err(|err| { + // FIXME: somehow this is reachable even when POST_MONO_CHECKS is on. + // Are we not always populating `required_consts`? + err.emit_note(*self.tcx); + err + })?; self.const_val_to_op(const_val, val.ty(), layout) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 775a834f2eeef..2c6a4de456d06 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -100,8 +100,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(_, _) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx), @@ -165,7 +164,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::type_name => Ty::new_static_str(self.tcx.tcx), _ => bug!(), }; - let val = self.ctfe_query(None, |tcx| { + let val = self.ctfe_query(|tcx| { tcx.const_eval_global_id(self.param_env, gid, Some(tcx.span)) })?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; @@ -307,7 +306,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let dist = { // Addresses are unsigned, so this is a `usize` computation. We have to do the // overflow check separately anyway. - let (val, overflowed, _ty) = { + let (val, overflowed) = { let a_offset = ImmTy::from_uint(a_offset, usize_layout); let b_offset = ImmTy::from_uint(b_offset, usize_layout); self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)? @@ -324,7 +323,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The signed form of the intrinsic allows this. If we interpret the // difference as isize, we'll get the proper signed difference. If that // seems *positive*, they were more than isize::MAX apart. - let dist = val.to_target_isize(self)?; + let dist = val.to_scalar().to_target_isize(self)?; if dist >= 0 { throw_ub_custom!( fluent::const_eval_offset_from_underflow, @@ -334,7 +333,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dist } else { // b >= a - let dist = val.to_target_isize(self)?; + let dist = val.to_scalar().to_target_isize(self)?; // If converting to isize produced a *negative* result, we had an overflow // because they were more than isize::MAX apart. if dist < 0 { @@ -504,9 +503,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. // First, check x % y != 0 (or if that computation overflows). - let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?; + let (res, overflow) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?; assert!(!overflow); // All overflow is UB, so this should never return on overflow. - if res.assert_bits(a.layout.size) != 0 { + if res.to_scalar().assert_bits(a.layout.size) != 0 { throw_ub_custom!( fluent::const_eval_exact_div_has_remainder, a = format!("{a}"), @@ -524,7 +523,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { r: &ImmTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Scalar> { assert!(matches!(mir_op, BinOp::Add | BinOp::Sub)); - let (val, overflowed, _ty) = self.overflowing_binary_op(mir_op, l, r)?; + let (val, overflowed) = self.overflowing_binary_op(mir_op, l, r)?; Ok(if overflowed { let size = l.layout.size; let num_bits = size.bits(); @@ -556,7 +555,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } else { - val + val.to_scalar() }) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index c9fd210241846..aaa674a598f84 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -9,7 +9,7 @@ use std::hash::Hash; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi as CallAbi; @@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment; use super::{ AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, - InterpResult, MPlaceTy, MemoryKind, OpTy, PlaceTy, Pointer, Provenance, Scalar, + InterpResult, MPlaceTy, MemoryKind, OpTy, PlaceTy, Pointer, Provenance, }; /// Data returned by Machine::stack_pop, @@ -238,7 +238,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { bin_op: mir::BinOp, left: &ImmTy<'tcx, Self::Provenance>, right: &ImmTy<'tcx, Self::Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)>; + ) -> InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)>; /// Called before writing the specified `local` of the `frame`. /// Since writing a ZST is not actually accessing memory or locals, this is never invoked diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 436c4d521a51c..ce666e6af3bdf 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -536,7 +536,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // We don't give a span -- statics don't need that, they cannot be generic or associated. - let val = self.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?; + let val = self.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; (val, Some(def_id)) } }; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index fdda98a50e8c7..99dba977a4395 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -8,7 +8,7 @@ use either::{Either, Left, Right}; use rustc_hir::def::Namespace; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; -use rustc_middle::ty::{ConstInt, Ty}; +use rustc_middle::ty::{ConstInt, Ty, TyCtxt}; use rustc_middle::{mir, ty}; use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size}; @@ -165,7 +165,15 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline(always)] pub fn from_immediate(imm: Immediate, layout: TyAndLayout<'tcx>) -> Self { - debug_assert!(layout.is_sized(), "immediates must be sized"); + debug_assert!( + match (imm, layout.abi) { + (Immediate::Scalar(..), Abi::Scalar(..)) => true, + (Immediate::ScalarPair(..), Abi::ScalarPair(..)) => true, + (Immediate::Uninit, _) if layout.is_sized() => true, + _ => false, + }, + "immediate {imm:?} does not fit to layout {layout:?}", + ); ImmTy { imm, layout } } @@ -194,6 +202,12 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { Self::from_scalar(Scalar::from_int(i, layout.size), layout) } + #[inline] + pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self { + let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap(); + Self::from_scalar(Scalar::from_bool(b), layout) + } + #[inline] pub fn to_const_int(self) -> ConstInt { assert!(self.layout.ty.is_integral()); @@ -448,7 +462,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { alloc_range(Size::ZERO, size), /*read_provenance*/ matches!(s, abi::Pointer(_)), )?; - Some(ImmTy { imm: scalar.into(), layout: mplace.layout }) + Some(ImmTy::from_scalar(scalar, mplace.layout)) } Abi::ScalarPair( abi::Scalar::Initialized { value: a, .. }, @@ -468,7 +482,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { alloc_range(b_offset, b_size), /*read_provenance*/ matches!(b, abi::Pointer(_)), )?; - Some(ImmTy { imm: Immediate::ScalarPair(a_val, b_val), layout: mplace.layout }) + Some(ImmTy::from_immediate(Immediate::ScalarPair(a_val, b_val), mplace.layout)) } _ => { // Neither a scalar nor scalar pair. @@ -514,11 +528,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Abi::Scalar(abi::Scalar::Initialized { .. }) | Abi::ScalarPair(abi::Scalar::Initialized { .. }, abi::Scalar::Initialized { .. }) ) { - span_bug!( - self.cur_span(), - "primitive read not possible for type: {:?}", - op.layout().ty - ); + span_bug!(self.cur_span(), "primitive read not possible for type: {}", op.layout().ty); } let imm = self.read_immediate_raw(op)?.right().unwrap(); if matches!(*imm, Immediate::Uninit) { @@ -660,19 +670,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("eval_place_to_op: got {:?}", op); // Sanity-check the type we ended up with. - debug_assert!( - mir_assign_valid_types( + if cfg!(debug_assertions) { + let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( + mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, + )?; + if !mir_assign_valid_types( *self.tcx, self.param_env, - self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty - )?)?, + self.layout_of(normalized_place_ty)?, op.layout, - ), - "eval_place of a MIR place with type {:?} produced an interpreter operand with type {:?}", - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, - op.layout.ty, - ); + ) { + span_bug!( + self.cur_span(), + "eval_place of a MIR place with type {} produced an interpreter operand with type {}", + normalized_place_ty, + op.layout.ty, + ) + } + } Ok(op) } @@ -692,7 +707,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(constant) => { let c = - self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; + self.subst_from_current_frame_and_normalize_erasing_regions(constant.const_)?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index eb0645780673c..b084864f3a730 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,7 +1,7 @@ use rustc_apfloat::Float; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_span::symbol::sym; use rustc_target::abi::Abi; @@ -20,9 +20,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: &ImmTy<'tcx, M::Provenance>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let (val, overflowed, ty) = self.overflowing_binary_op(op, &left, &right)?; + let (val, overflowed) = self.overflowing_binary_op(op, &left, &right)?; debug_assert_eq!( - Ty::new_tup(self.tcx.tcx, &[ty, self.tcx.types.bool]), + Ty::new_tup(self.tcx.tcx, &[val.layout.ty, self.tcx.types.bool]), dest.layout.ty, "type mismatch for result of {op:?}", ); @@ -30,7 +30,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Abi::ScalarPair(..) = dest.layout.abi { // We can use the optimized path and avoid `place_field` (which might do // `force_allocation`). - let pair = Immediate::ScalarPair(val, Scalar::from_bool(overflowed)); + let pair = Immediate::ScalarPair(val.to_scalar(), Scalar::from_bool(overflowed)); self.write_immediate(pair, dest)?; } else { assert!(self.tcx.sess.opts.unstable_opts.randomize_layout); @@ -38,7 +38,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // do a component-wise write here. This code path is slower than the above because // `place_field` will have to `force_allocate` locals here. let val_field = self.project_field(dest, 0)?; - self.write_scalar(val, &val_field)?; + self.write_scalar(val.to_scalar(), &val_field)?; let overflowed_field = self.project_field(dest, 1)?; self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?; } @@ -54,9 +54,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: &ImmTy<'tcx, M::Provenance>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let (val, _overflowed, ty) = self.overflowing_binary_op(op, left, right)?; - assert_eq!(ty, dest.layout.ty, "type mismatch for result of {op:?}"); - self.write_scalar(val, dest) + let val = self.wrapping_binary_op(op, left, right)?; + assert_eq!(val.layout.ty, dest.layout.ty, "type mismatch for result of {op:?}"); + self.write_immediate(*val, dest) } } @@ -66,7 +66,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: char, r: char, - ) -> (Scalar, bool, Ty<'tcx>) { + ) -> (ImmTy<'tcx, M::Provenance>, bool) { use rustc_middle::mir::BinOp::*; let res = match bin_op { @@ -78,7 +78,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ge => l >= r, _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op), }; - (Scalar::from_bool(res), false, self.tcx.types.bool) + (ImmTy::from_bool(res, *self.tcx), false) } fn binary_bool_op( @@ -86,7 +86,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: bool, r: bool, - ) -> (Scalar, bool, Ty<'tcx>) { + ) -> (ImmTy<'tcx, M::Provenance>, bool) { use rustc_middle::mir::BinOp::*; let res = match bin_op { @@ -101,33 +101,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => l ^ r, _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op), }; - (Scalar::from_bool(res), false, self.tcx.types.bool) + (ImmTy::from_bool(res, *self.tcx), false) } fn binary_float_op>>( &self, bin_op: mir::BinOp, - ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, l: F, r: F, - ) -> (Scalar, bool, Ty<'tcx>) { + ) -> (ImmTy<'tcx, M::Provenance>, bool) { use rustc_middle::mir::BinOp::*; - let (val, ty) = match bin_op { - Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), - Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), - Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), - Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), - Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), - Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), - Add => ((l + r).value.into(), ty), - Sub => ((l - r).value.into(), ty), - Mul => ((l * r).value.into(), ty), - Div => ((l / r).value.into(), ty), - Rem => ((l % r).value.into(), ty), + let val = match bin_op { + Eq => ImmTy::from_bool(l == r, *self.tcx), + Ne => ImmTy::from_bool(l != r, *self.tcx), + Lt => ImmTy::from_bool(l < r, *self.tcx), + Le => ImmTy::from_bool(l <= r, *self.tcx), + Gt => ImmTy::from_bool(l > r, *self.tcx), + Ge => ImmTy::from_bool(l >= r, *self.tcx), + Add => ImmTy::from_scalar((l + r).value.into(), layout), + Sub => ImmTy::from_scalar((l - r).value.into(), layout), + Mul => ImmTy::from_scalar((l * r).value.into(), layout), + Div => ImmTy::from_scalar((l / r).value.into(), layout), + Rem => ImmTy::from_scalar((l % r).value.into(), layout), _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op), }; - (val, false, ty) + (val, false) } fn binary_int_op( @@ -138,7 +138,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { left_layout: TyAndLayout<'tcx>, r: u128, right_layout: TyAndLayout<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { use rustc_middle::mir::BinOp::*; let throw_ub_on_overflow = match bin_op { @@ -200,19 +200,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } - return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty)); + return Ok((ImmTy::from_uint(truncated, left_layout), overflow)); } // For the remaining ops, the types must be the same on both sides if left_layout.ty != right_layout.ty { span_bug!( self.cur_span(), - "invalid asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})", - bin_op, - l, - left_layout.ty, - r, - right_layout.ty, + "invalid asymmetric binary op {bin_op:?}: {l:?} ({l_ty}), {r:?} ({r_ty})", + l_ty = left_layout.ty, + r_ty = right_layout.ty, ) } @@ -230,7 +227,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(op) = op { let l = self.sign_extend(l, left_layout) as i128; let r = self.sign_extend(r, right_layout) as i128; - return Ok((Scalar::from_bool(op(&l, &r)), false, self.tcx.types.bool)); + return Ok((ImmTy::from_bool(op(&l, &r), *self.tcx), false)); } let op: Option (i128, bool)> = match bin_op { Div if r == 0 => throw_ub!(DivisionByZero), @@ -267,22 +264,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name); } - return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty)); + return Ok((ImmTy::from_uint(truncated, left_layout), overflow)); } } - let (val, ty) = match bin_op { - Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), - Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), + let val = match bin_op { + Eq => ImmTy::from_bool(l == r, *self.tcx), + Ne => ImmTy::from_bool(l != r, *self.tcx), - Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), - Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), - Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), - Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), + Lt => ImmTy::from_bool(l < r, *self.tcx), + Le => ImmTy::from_bool(l <= r, *self.tcx), + Gt => ImmTy::from_bool(l > r, *self.tcx), + Ge => ImmTy::from_bool(l >= r, *self.tcx), - BitOr => (Scalar::from_uint(l | r, size), left_layout.ty), - BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty), - BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty), + BitOr => ImmTy::from_uint(l | r, left_layout), + BitAnd => ImmTy::from_uint(l & r, left_layout), + BitXor => ImmTy::from_uint(l ^ r, left_layout), Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => { assert!(!left_layout.abi.is_signed()); @@ -304,12 +301,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name); } - return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty)); + return Ok((ImmTy::from_uint(truncated, left_layout), overflow)); } _ => span_bug!( self.cur_span(), - "invalid binary op {:?}: {:?}, {:?} (both {:?})", + "invalid binary op {:?}: {:?}, {:?} (both {})", bin_op, l, r, @@ -317,7 +314,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - Ok((val, false, ty)) + Ok((val, false)) } fn binary_ptr_op( @@ -325,7 +322,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { use rustc_middle::mir::BinOp::*; match bin_op { @@ -336,7 +333,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty; let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; - Ok((Scalar::from_maybe_pointer(offset_ptr, self), false, left.layout.ty)) + Ok(( + ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout), + false, + )) } // Fall back to machine hook so Miri can support more pointer ops. @@ -344,16 +344,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - /// Returns the result of the specified operation, whether it overflowed, and - /// the result type. + /// Returns the result of the specified operation, and whether it overflowed. pub fn overflowing_binary_op( &self, bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { trace!( - "Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", + "Running binary op {:?}: {:?} ({}), {:?} ({})", bin_op, *left, left.layout.ty, @@ -376,15 +375,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::Float(fty) => { assert_eq!(left.layout.ty, right.layout.ty); - let ty = left.layout.ty; + let layout = left.layout; let left = left.to_scalar(); let right = right.to_scalar(); Ok(match fty { FloatTy::F32 => { - self.binary_float_op(bin_op, ty, left.to_f32()?, right.to_f32()?) + self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?) } FloatTy::F64 => { - self.binary_float_op(bin_op, ty, left.to_f64()?, right.to_f64()?) + self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?) } }) } @@ -392,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // the RHS type can be different, e.g. for shifts -- but it has to be integral, too assert!( right.layout.ty.is_integral(), - "Unexpected types for BinOp: {:?} {:?} {:?}", + "Unexpected types for BinOp: {} {:?} {}", left.layout.ty, bin_op, right.layout.ty @@ -407,7 +406,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // (Even when both sides are pointers, their type might differ, see issue #91636) assert!( right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), - "Unexpected types for BinOp: {:?} {:?} {:?}", + "Unexpected types for BinOp: {} {:?} {}", left.layout.ty, bin_op, right.layout.ty @@ -417,22 +416,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => span_bug!( self.cur_span(), - "Invalid MIR: bad LHS type for binop: {:?}", + "Invalid MIR: bad LHS type for binop: {}", left.layout.ty ), } } - /// Typed version of `overflowing_binary_op`, returning an `ImmTy`. Also ignores overflows. #[inline] - pub fn binary_op( + pub fn wrapping_binary_op( &self, bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - let (val, _overflow, ty) = self.overflowing_binary_op(bin_op, left, right)?; - Ok(ImmTy::from_scalar(val, self.layout_of(ty)?)) + let (val, _overflow) = self.overflowing_binary_op(bin_op, left, right)?; + Ok(val) } /// Returns the result of the specified operation, whether it overflowed, and @@ -441,12 +439,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, un_op: mir::UnOp, val: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { use rustc_middle::mir::UnOp::*; let layout = val.layout; let val = val.to_scalar(); - trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty); + trace!("Running unary op {:?}: {:?} ({})", un_op, val, layout.ty); match layout.ty.kind() { ty::Bool => { @@ -455,7 +453,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Not => !val, _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op), }; - Ok((Scalar::from_bool(res), false, self.tcx.types.bool)) + Ok((ImmTy::from_bool(res, *self.tcx), false)) } ty::Float(fty) => { let res = match (un_op, fty) { @@ -463,7 +461,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op), }; - Ok((res, false, layout.ty)) + Ok((ImmTy::from_scalar(res, layout), false)) } _ => { assert!(layout.ty.is_integral()); @@ -482,17 +480,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (truncated, overflow || self.sign_extend(truncated, layout) != res) } }; - Ok((Scalar::from_uint(res, layout.size), overflow, layout.ty)) + Ok((ImmTy::from_uint(res, layout), overflow)) } } } - pub fn unary_op( + #[inline] + pub fn wrapping_unary_op( &self, un_op: mir::UnOp, val: &ImmTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - let (val, _overflow, ty) = self.overflowing_unary_op(un_op, val)?; - Ok(ImmTy::from_scalar(val, self.layout_of(ty)?)) + let (val, _overflow) = self.overflowing_unary_op(un_op, val)?; + Ok(val) } } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index fb9aa9d3abe6c..79448f07cae2e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -460,7 +460,7 @@ where trace!("deref to {} on {:?}", val.layout.ty, *val); if val.layout.ty.is_box() { - bug!("dereferencing {:?}", val.layout.ty); + bug!("dereferencing {}", val.layout.ty); } let mplace = self.ref_to_mplace(&val)?; @@ -573,19 +573,24 @@ where trace!("{:?}", self.dump_place(&place)); // Sanity-check the type we ended up with. - debug_assert!( - mir_assign_valid_types( + if cfg!(debug_assertions) { + let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( + mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, + )?; + if !mir_assign_valid_types( *self.tcx, self.param_env, - self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty - )?)?, + self.layout_of(normalized_place_ty)?, place.layout, - ), - "eval_place of a MIR place with type {:?} produced an interpreter place with type {:?}", - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, - place.layout.ty, - ); + ) { + span_bug!( + self.cur_span(), + "eval_place of a MIR place with type {} produced an interpreter place with type {}", + normalized_place_ty, + place.layout.ty, + ) + } + } Ok(place) } @@ -835,7 +840,7 @@ where if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), - "type mismatch when copying!\nsrc: {:?},\ndest: {:?}", + "type mismatch when copying!\nsrc: {},\ndest: {}", src.layout().ty, dest.layout().ty, ); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 6c720ac4a574d..70df3d8fd782c 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -316,7 +316,11 @@ where { use rustc_middle::mir::ProjectionElem::*; Ok(match proj_elem { - OpaqueCast(ty) => base.transmute(self.layout_of(ty)?, self)?, + OpaqueCast(ty) => { + span_bug!(self.cur_span(), "OpaqueCast({ty}) encountered after borrowck") + } + // We don't want anything happening here, this is here as a dummy. + Subtype(_) => base.transmute(base.layout(), self)?, Field(field, _) => self.project_field(base, field.index())?, Downcast(_, variant) => self.project_downcast(base, variant)?, Deref => self.deref_pointer(&base.to_op(self)?)?.into(), diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index cf1f7ff75e1af..284e13407f7e4 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -177,7 +177,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { UnaryOp(un_op, ref operand) => { // The operand always has the same type as the result. let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?; - let val = self.unary_op(un_op, &val)?; + let val = self.wrapping_unary_op(un_op, &val)?; assert_eq!(val.layout, dest.layout, "layout mismatch for result of {un_op:?}"); self.write_immediate(*val, &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index e15499bc68d0a..578dd6622aaf4 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -98,14 +98,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (const_int, target) in targets.iter() { // Compare using MIR BinOp::Eq, to also support pointer values. // (Avoiding `self.binary_op` as that does some redundant layout computation.) - let res = self - .overflowing_binary_op( - mir::BinOp::Eq, - &discr, - &ImmTy::from_uint(const_int, discr.layout), - )? - .0; - if res.to_bool()? { + let res = self.wrapping_binary_op( + mir::BinOp::Eq, + &discr, + &ImmTy::from_uint(const_int, discr.layout), + )?; + if res.to_scalar().to_bool()? { target_block = target; break; } @@ -151,7 +149,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => span_bug!( terminator.source_info.span, - "invalid callee of type {:?}", + "invalid callee of type {}", func.layout.ty ), }; @@ -681,10 +679,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.storage_live(local)?; // Must be a tuple let ty::Tuple(fields) = ty.kind() else { - span_bug!( - self.cur_span(), - "non-tuple type for `spread_arg`: {ty:?}" - ) + span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}") }; for (i, field_ty) in fields.iter().enumerate() { let dest = dest.project_deeper( @@ -926,7 +921,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { target: mir::BasicBlock, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - trace!("drop_in_place: {:?},\n {:?}, {:?}", *place, place.layout.ty, instance); + trace!("drop_in_place: {:?},\n instance={:?}", place, instance); // We take the address of the object. This may well be unaligned, which is fine // for us here. However, unaligned accesses will probably make the actual drop // implementation fail -- a problem shared by rustc. diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index b33194423887c..eb639ded70ffd 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{ }; use std::ops::ControlFlow; -/// Checks whether a type contains generic parameters which require substitution. +/// Checks whether a type contains generic parameters which must be instantiated. /// /// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization /// types may be "concrete enough" even though they still contain generic parameters in @@ -43,7 +43,8 @@ where .try_into() .expect("more generic parameters than can fit into a `u32`"); // Only recurse when generic parameters in fns, closures and generators - // are used and require substitution. + // are used and have to be instantiated. + // // Just in case there are closures or generators within this subst, // recurse. if unused_params.is_used(index) && subst.has_param() { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 8e2b35fd5b619..3e023a89648e5 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -583,7 +583,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | ty::Bound(..) | ty::Param(..) | ty::Alias(..) - | ty::GeneratorWitnessMIR(..) | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index c126f749bf328..8bb409cea08a0 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -38,8 +38,7 @@ pub use errors::ReportErrorExt; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; -use rustc_middle::query::Providers; -use rustc_middle::ty; +use rustc_middle::{ty, util::Providers}; fluent_messages! { "../messages.ftl" } @@ -52,8 +51,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_for_diagnostics = - |tcx, (cv, ty)| const_eval::try_destructure_mir_constant_for_diagnostics(tcx, cv, ty); + providers.hooks.try_destructure_mir_constant_for_diagnostics = + const_eval::try_destructure_mir_constant_for_diagnostics; 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 f288ddc25d3a4..f8f9bfb047068 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -167,7 +167,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { false } - hir::ConstContext::Const | hir::ConstContext::Static(_) => { + hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => { let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) .into_engine(ccx.tcx, &ccx.body) .iterate_to_fixpoint() @@ -237,7 +237,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { if self.const_kind() == hir::ConstContext::ConstFn { for (idx, local) in body.local_decls.iter_enumerated() { // Handle the return place below. - if idx == RETURN_PLACE || local.internal { + if idx == RETURN_PLACE { continue; } @@ -664,6 +664,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | ProjectionElem::Downcast(..) | ProjectionElem::OpaqueCast(..) | ProjectionElem::Subslice { .. } + | ProjectionElem::Subtype(..) | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {} } @@ -742,7 +743,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); } // Attempting to call a trait method? @@ -886,7 +887,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // At this point, we are calling a function, `callee`, whose `DefId` is known... - // `begin_panic` and `panic_display` are generic functions that accept + // `begin_panic` and `#[rustc_const_panic_str]` functions accept generic // types other than str. Check to enforce that only str can be used in // const-eval. @@ -898,8 +899,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - // const-eval of the `panic_display` fn assumes the argument is `&&str` - if Some(callee) == tcx.lang_items().panic_display() { + // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str` + if tcx.has_attr(callee, sym::rustc_const_panic_str) { match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => { 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 b1b2859ef9dc7..de3186a53c165 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -306,6 +306,7 @@ where ProjectionElem::Index(index) if in_local(index) => return true, ProjectionElem::Deref + | ProjectionElem::Subtype(_) | ProjectionElem::Field(_, _) | ProjectionElem::OpaqueCast(_) | ProjectionElem::ConstantIndex { .. } @@ -346,8 +347,8 @@ where }; // Check the qualifs of the value of `const` items. - let uneval = match constant.literal { - ConstantKind::Ty(ct) + let uneval = match constant.const_ { + Const::Ty(ct) if matches!( ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_) @@ -355,11 +356,11 @@ where { None } - ConstantKind::Ty(c) => { + Const::Ty(c) => { bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c) } - ConstantKind::Unevaluated(uv, _) => Some(uv), - ConstantKind::Val(..) => None, + Const::Unevaluated(uv, _) => Some(uv), + Const::Val(..) => None, }; if let Some(mir::UnevaluatedConst { def, args: _, promoted }) = uneval { @@ -383,5 +384,5 @@ where } // Otherwise use the qualifs of the type. - Q::in_any_value_of_ty(cx, constant.literal.ty()) + Q::in_any_value_of_ty(cx, constant.const_.ty()) } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index d79c65f1d1fee..8ede3bdd2b60a 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -357,7 +357,9 @@ impl<'tcx> Validator<'_, 'tcx> { return Err(Unpromotable); } - ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {} + ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subtype(_) + | ProjectionElem::Subslice { .. } => {} ProjectionElem::Index(local) => { let mut promotable = false; @@ -372,7 +374,7 @@ impl<'tcx> Validator<'_, 'tcx> { StatementKind::Assign(box ( _, Rvalue::Use(Operand::Constant(c)), - )) => c.literal.try_eval_target_usize(self.tcx, self.param_env), + )) => c.const_.try_eval_target_usize(self.tcx, self.param_env), _ => None, } } else { @@ -554,7 +556,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Integer division: the RHS must be a non-zero const. let const_val = match rhs { Operand::Constant(c) => { - c.literal.try_eval_bits(self.tcx, self.param_env, lhs_ty) + c.const_.try_eval_bits(self.tcx, self.param_env) } _ => None, }; @@ -644,7 +646,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Everywhere else, we require `#[rustc_promotable]` on the callee. let promote_all_const_fn = matches!( self.const_kind, - Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { inline: false }) ); if !promote_all_const_fn { if let ty::FnDef(def_id, _) = *fn_ty.kind() { @@ -766,10 +768,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { if self.keep_original { rhs.clone() } else { - let unit = Rvalue::Use(Operand::Constant(Box::new(Constant { + let unit = Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: statement.source_info.span, user_ty: None, - literal: ConstantKind::zero_sized(self.tcx.types.unit), + const_: Const::zero_sized(self.tcx.types.unit), }))); mem::replace(rhs, unit) }, @@ -844,10 +846,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def)); let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) }; - Operand::Constant(Box::new(Constant { + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, - literal: ConstantKind::Unevaluated(uneval, ty), + const_: Const::Unevaluated(uneval, ty), })) }; @@ -1041,8 +1043,8 @@ pub fn is_const_fn_in_array_repeat_expression<'tcx>( if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) = &block.terminator { - if let Operand::Constant(box Constant { literal, .. }) = func { - if let ty::FnDef(def_id, _) = *literal.ty().kind() { + if let Operand::Constant(box ConstOperand { const_, .. }) = func { + if let ty::FnDef(def_id, _) = *const_.ty().kind() { if destination == place { if ccx.tcx.is_const_fn(def_id) { return true; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 2f5f2ad6534ad..4711f7b47cccc 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::Reveal; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; @@ -16,6 +16,8 @@ use rustc_target::spec::abi::Abi; use crate::util::is_within_packed; +use crate::util::relate_types; + #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum EdgeKind { Unwind, @@ -558,8 +560,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } -/// A faster version of the validation pass that only checks those things which may break when apply -/// generic substitutions. +/// A faster version of the validation pass that only checks those things which may break when +/// instantiating any generic parameters. pub fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, @@ -602,7 +604,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - crate::util::is_subtype(self.tcx, self.param_env, src, dest) + // After borrowck subtyping should be fully explicit via + // `Subtype` projections. + let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + Variance::Invariant + } else { + Variance::Covariant + }; + + crate::util::relate_types(self.tcx, self.param_env, variance, src, dest) } } @@ -633,6 +643,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location: Location, ) { match elem { + ProjectionElem::OpaqueCast(ty) + if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) => + { + self.fail( + location, + format!("explicit opaque type cast to `{ty}` after `RevealAll`"), + ) + } ProjectionElem::Index(index) => { let index_ty = self.body.local_decls[index].ty; if index_ty != self.tcx.types.usize { @@ -745,6 +763,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } + ProjectionElem::Subtype(ty) => { + if !relate_types( + self.tcx, + self.param_env, + Variance::Covariant, + ty, + place_ref.ty(&self.body.local_decls, self.tcx).ty, + ) { + self.fail( + location, + format!( + "Failed subtyping {ty:#?} and {:#?}", + place_ref.ty(&self.body.local_decls, self.tcx).ty + ), + ) + } + } _ => {} } self.super_projection_elem(place_ref, elem, context, location); @@ -1080,6 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // LHS and RHS of the assignment must have the same type. let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty; let right_ty = rvalue.ty(&self.body.local_decls, self.tcx); + if !self.mir_assign_valid_types(right_ty, left_ty) { self.fail( location, diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 2e0643afb3918..8642dfccd7843 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -21,10 +21,18 @@ where }; let ty = place.ty(local_decls, tcx).ty; + let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {}); match tcx.layout_of(param_env.and(ty)) { - Ok(layout) if layout.align.abi <= pack => { + Ok(layout) + if layout.align.abi <= pack + && (layout.is_sized() + || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) => + { // If the packed alignment is greater or equal to the field alignment, the type won't be // further disaligned. + // However we need to ensure the field is sized; for unsized fields, `layout.align` is + // just an approximation -- except when the unsized tail is a slice, where the alignment + // is fully determined by the type. debug!( "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", place, diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index 83376c8e99289..265ca0c7884ce 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::{DefiningAnchor, ObligationCause}; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance}; use rustc_trait_selection::traits::ObligationCtxt; /// Returns whether the two types are equal up to subtyping. @@ -24,16 +24,22 @@ pub fn is_equal_up_to_subtyping<'tcx>( } // Check for subtyping in either direction. - is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src) + relate_types(tcx, param_env, Variance::Covariant, src, dest) + || relate_types(tcx, param_env, Variance::Covariant, dest, src) } /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. /// +/// When validating assignments, the variance should be `Covariant`. When checking +/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant` +/// because we want to check for type equality. +/// /// This mostly ignores opaque types as it can be used in constraining contexts /// while still computing the final underlying type. -pub fn is_subtype<'tcx>( +pub fn relate_types<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, + variance: Variance, src: Ty<'tcx>, dest: Ty<'tcx>, ) -> bool { @@ -48,7 +54,7 @@ pub fn is_subtype<'tcx>( let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); let dest = ocx.normalize(&cause, param_env, dest); - match ocx.sub(&cause, param_env, src, dest) { + match ocx.relate(&cause, param_env, variance, src, dest) { Ok(()) => {} Err(_) => return false, }; diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 0aef7fa469e4b..040b3071e6f87 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -7,7 +7,7 @@ mod type_name; pub use self::alignment::{is_disaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; -pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; +pub use self::compare_types::{is_equal_up_to_subtyping, relate_types}; pub use self::type_name::type_name; /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 14a840ad1b1e8..a924afda6f07a 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -64,8 +64,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"), ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"), - ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), - ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"), + ty::GeneratorWitness(..) => bug!("type_name: unexpected `GeneratorWitness`"), } } diff --git a/compiler/rustc_data_structures/src/flock/unix.rs b/compiler/rustc_data_structures/src/flock/unix.rs index 4e5297d582e07..eff9e8f838fe7 100644 --- a/compiler/rustc_data_structures/src/flock/unix.rs +++ b/compiler/rustc_data_structures/src/flock/unix.rs @@ -21,8 +21,16 @@ impl Lock { let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK }; let mut flock: libc::flock = unsafe { mem::zeroed() }; - flock.l_type = lock_type as libc::c_short; - flock.l_whence = libc::SEEK_SET as libc::c_short; + #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] + { + flock.l_type = lock_type as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + } + #[cfg(all(target_os = "hurd", target_arch = "x86"))] + { + flock.l_type = lock_type as libc::c_int; + flock.l_whence = libc::SEEK_SET as libc::c_int; + } flock.l_start = 0; flock.l_len = 0; @@ -39,8 +47,16 @@ impl Lock { impl Drop for Lock { fn drop(&mut self) { let mut flock: libc::flock = unsafe { mem::zeroed() }; - flock.l_type = libc::F_UNLCK as libc::c_short; - flock.l_whence = libc::SEEK_SET as libc::c_short; + #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] + { + flock.l_type = libc::F_UNLCK as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + } + #[cfg(all(target_os = "hurd", target_arch = "x86"))] + { + flock.l_type = libc::F_UNLCK as libc::c_int; + flock.l_whence = libc::SEEK_SET as libc::c_int; + } flock.l_start = 0; flock.l_len = 0; diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 4075481e56160..9685ad24a9767 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -26,7 +26,42 @@ rustc_index::newtype_index! { struct PreorderIndex {} } -pub fn dominators(graph: &G) -> Dominators { +#[derive(Clone, Debug)] +pub struct Dominators { + kind: Kind, +} + +#[derive(Clone, Debug)] +enum Kind { + /// A representation optimized for a small path graphs. + Path, + General(Inner), +} + +pub fn dominators(g: &G) -> Dominators { + // We often encounter MIR bodies with 1 or 2 basic blocks. Special case the dominators + // computation and representation for those cases. + if is_small_path_graph(g) { + Dominators { kind: Kind::Path } + } else { + Dominators { kind: Kind::General(dominators_impl(g)) } + } +} + +fn is_small_path_graph(g: &G) -> bool { + if g.start_node().index() != 0 { + return false; + } + if g.num_nodes() == 1 { + return true; + } + if g.num_nodes() == 2 { + return g.successors(g.start_node()).any(|n| n.index() == 1); + } + false +} + +fn dominators_impl(graph: &G) -> Inner { // compute the post order index (rank) for each node let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes()); @@ -245,7 +280,7 @@ pub fn dominators(graph: &G) -> Dominators { let time = compute_access_time(start_node, &immediate_dominators); - Dominators { start_node, post_order_rank, immediate_dominators, time } + Inner { post_order_rank, immediate_dominators, time } } /// Evaluate the link-eval virtual forest, providing the currently minimum semi @@ -310,8 +345,7 @@ fn compress( /// Tracks the list of dominators for each node. #[derive(Clone, Debug)] -pub struct Dominators { - start_node: N, +struct Inner { post_order_rank: IndexVec, // Even though we track only the immediate dominator of each node, it's // possible to get its full list of dominators by looking up the dominator @@ -323,12 +357,24 @@ pub struct Dominators { impl Dominators { /// Returns true if node is reachable from the start node. pub fn is_reachable(&self, node: Node) -> bool { - node == self.start_node || self.immediate_dominators[node].is_some() + match &self.kind { + Kind::Path => true, + Kind::General(g) => g.time[node].start != 0, + } } /// Returns the immediate dominator of node, if any. pub fn immediate_dominator(&self, node: Node) -> Option { - self.immediate_dominators[node] + match &self.kind { + Kind::Path => { + if 0 < node.index() { + Some(Node::new(node.index() - 1)) + } else { + None + } + } + Kind::General(g) => g.immediate_dominators[node], + } } /// Provides an iterator over each dominator up the CFG, for the given Node. @@ -343,7 +389,10 @@ impl Dominators { /// of two unrelated nodes will also be consistent, but otherwise the order has no /// meaning.) This method cannot be used to determine if either Node dominates the other. pub fn cmp_in_dominator_order(&self, lhs: Node, rhs: Node) -> Ordering { - self.post_order_rank[rhs].cmp(&self.post_order_rank[lhs]) + match &self.kind { + Kind::Path => lhs.index().cmp(&rhs.index()), + Kind::General(g) => g.post_order_rank[rhs].cmp(&g.post_order_rank[lhs]), + } } /// Returns true if `a` dominates `b`. @@ -352,10 +401,15 @@ impl Dominators { /// /// Panics if `b` is unreachable. pub fn dominates(&self, a: Node, b: Node) -> bool { - let a = self.time[a]; - let b = self.time[b]; - assert!(b.start != 0, "node {b:?} is not reachable"); - a.start <= b.start && b.finish <= a.finish + match &self.kind { + Kind::Path => a.index() <= b.index(), + Kind::General(g) => { + let a = g.time[a]; + let b = g.time[b]; + assert!(b.start != 0, "node {b:?} is not reachable"); + a.start <= b.start && b.finish <= a.finish + } + } } } diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs index 5472bb8087ec7..39725ba4301be 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs @@ -6,12 +6,11 @@ use super::super::tests::TestGraph; fn diamond() { let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); - let dominators = dominators(&graph); - let immediate_dominators = &dominators.immediate_dominators; - assert_eq!(immediate_dominators[0], None); - assert_eq!(immediate_dominators[1], Some(0)); - assert_eq!(immediate_dominators[2], Some(0)); - assert_eq!(immediate_dominators[3], Some(0)); + let d = dominators(&graph); + assert_eq!(d.immediate_dominator(0), None); + assert_eq!(d.immediate_dominator(1), Some(0)); + assert_eq!(d.immediate_dominator(2), Some(0)); + assert_eq!(d.immediate_dominator(3), Some(0)); } #[test] @@ -22,15 +21,14 @@ fn paper() { &[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), (2, 1)], ); - let dominators = dominators(&graph); - let immediate_dominators = &dominators.immediate_dominators; - assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph - assert_eq!(immediate_dominators[1], Some(6)); - assert_eq!(immediate_dominators[2], Some(6)); - assert_eq!(immediate_dominators[3], Some(6)); - assert_eq!(immediate_dominators[4], Some(6)); - assert_eq!(immediate_dominators[5], Some(6)); - assert_eq!(immediate_dominators[6], None); + let d = dominators(&graph); + assert_eq!(d.immediate_dominator(0), None); // <-- note that 0 is not in graph + assert_eq!(d.immediate_dominator(1), Some(6)); + assert_eq!(d.immediate_dominator(2), Some(6)); + assert_eq!(d.immediate_dominator(3), Some(6)); + assert_eq!(d.immediate_dominator(4), Some(6)); + assert_eq!(d.immediate_dominator(5), Some(6)); + assert_eq!(d.immediate_dominator(6), None); } #[test] @@ -47,11 +45,11 @@ fn paper_slt() { #[test] fn immediate_dominator() { let graph = TestGraph::new(1, &[(1, 2), (2, 3)]); - let dominators = dominators(&graph); - assert_eq!(dominators.immediate_dominator(0), None); - assert_eq!(dominators.immediate_dominator(1), None); - assert_eq!(dominators.immediate_dominator(2), Some(1)); - assert_eq!(dominators.immediate_dominator(3), Some(2)); + let d = dominators(&graph); + assert_eq!(d.immediate_dominator(0), None); + assert_eq!(d.immediate_dominator(1), None); + assert_eq!(d.immediate_dominator(2), Some(1)); + assert_eq!(d.immediate_dominator(3), Some(2)); } #[test] @@ -75,8 +73,7 @@ fn transitive_dominator() { ], ); - let dom_tree = dominators(&graph); - let immediate_dominators = &dom_tree.immediate_dominators; - assert_eq!(immediate_dominators[2], Some(0)); - assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1). + let d = dominators(&graph); + assert_eq!(d.immediate_dominator(2), Some(0)); + assert_eq!(d.immediate_dominator(3), Some(0)); // This used to return Some(1). } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 7d037ddfa986c..461ec3a90ed97 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -51,9 +51,10 @@ use std::fmt; pub use rustc_index::static_assert_size; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -pub fn cold_path R, R>(f: F) -> R { +pub fn outline R, R>(f: F) -> R { f() } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 3c76c2b79911a..e688feb5fe176 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -81,8 +81,8 @@ //! //! [mm]: https://github.com/rust-lang/measureme/ -use crate::cold_path; use crate::fx::FxHashMap; +use crate::outline; use std::borrow::Borrow; use std::collections::hash_map::Entry; @@ -697,7 +697,7 @@ impl<'a> TimingGuard<'a> { #[inline] pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) { if let Some(guard) = self.0 { - cold_path(|| { + outline(|| { let event_id = StringId::new_virtual(query_invocation_id.0); let event_id = EventId::from_virtual(event_id); guard.finish_with_override_event_id(event_id); diff --git a/compiler/rustc_data_structures/src/small_c_str.rs b/compiler/rustc_data_structures/src/small_c_str.rs index 719e4e3d97443..349fd7f9769d9 100644 --- a/compiler/rustc_data_structures/src/small_c_str.rs +++ b/compiler/rustc_data_structures/src/small_c_str.rs @@ -79,3 +79,9 @@ impl<'a> FromIterator<&'a str> for SmallCStr { Self { data } } } + +impl From<&ffi::CStr> for SmallCStr { + fn from(s: &ffi::CStr) -> Self { + Self { data: SmallVec::from_slice(s.to_bytes()) } + } +} diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 1f838cc4648dc..ffafdba13cea1 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -6,7 +6,7 @@ use std::ptr; use std::sync::Arc; #[cfg(parallel_compiler)] -use {crate::cold_path, crate::sync::CacheAligned}; +use {crate::outline, crate::sync::CacheAligned}; /// A pointer to the `RegistryData` which uniquely identifies a registry. /// This identifier can be reused if the registry gets freed. @@ -25,11 +25,7 @@ impl RegistryId { fn verify(self) -> usize { let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get())); - if id == self { - index - } else { - cold_path(|| panic!("Unable to verify registry association")) - } + if id == self { index } else { outline(|| panic!("Unable to verify registry association")) } } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 65c7aed3f1078..1b3f39e69e153 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1287,17 +1287,21 @@ pub fn ice_path() -> &'static Option { if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() { return None; } - if let Ok("0") = std::env::var("RUST_BACKTRACE").as_deref() { + if let Some(s) = std::env::var_os("RUST_BACKTRACE") && s == "0" { return None; } - let mut path = match std::env::var("RUSTC_ICE").as_deref() { - // Explicitly opting out of writing ICEs to disk. - Ok("0") => return None, - Ok(s) => PathBuf::from(s), - Err(_) => std::env::current_dir().unwrap_or_default(), + let mut path = match std::env::var_os("RUSTC_ICE") { + Some(s) => { + if s == "0" { + // Explicitly opting out of writing ICEs to disk. + return None; + } + PathBuf::from(s) + } + None => std::env::current_dir().unwrap_or_default(), }; let now: OffsetDateTime = SystemTime::now().into(); - let file_now = now.format(&Rfc3339).unwrap_or(String::new()); + let file_now = now.format(&Rfc3339).unwrap_or_default(); let pid = std::process::id(); path.push(format!("rustc-ice-{file_now}-{pid}.txt")); Some(path) @@ -1322,7 +1326,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) // by the user. Compiler developers and other rustc users can // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE" // (e.g. `RUST_BACKTRACE=1`) - if std::env::var("RUST_BACKTRACE").is_err() { + if std::env::var_os("RUST_BACKTRACE").is_none() { std::env::set_var("RUST_BACKTRACE", "full"); } @@ -1411,12 +1415,11 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: static FIRST_PANIC: AtomicBool = AtomicBool::new(true); - let file = if let Some(path) = ice_path().as_ref() { + let file = if let Some(path) = ice_path() { // Create the ICE dump target file. match crate::fs::File::options().create(true).append(true).open(&path) { Ok(mut file) => { - handler - .emit_note(session_diagnostics::IcePath { path: path.display().to_string() }); + handler.emit_note(session_diagnostics::IcePath { path: path.clone() }); if FIRST_PANIC.swap(false, Ordering::SeqCst) { let _ = write!(file, "\n\nrustc version: {version}\nplatform: {triple}"); } @@ -1425,10 +1428,10 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: Err(err) => { // The path ICE couldn't be written to disk, provide feedback to the user as to why. handler.emit_warning(session_diagnostics::IcePathError { - path: path.display().to_string(), + path: path.clone(), error: err.to_string(), - env_var: std::env::var("RUSTC_ICE") - .ok() + env_var: std::env::var_os("RUSTC_ICE") + .map(PathBuf::from) .map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }), }); handler.emit_note(session_diagnostics::IceVersion { version, triple }); diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 5eb587c54d990..442989f8de83a 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -52,13 +52,13 @@ pub(crate) struct IceVersion<'a> { #[derive(Diagnostic)] #[diag(driver_impl_ice_path)] pub(crate) struct IcePath { - pub path: String, + pub path: std::path::PathBuf, } #[derive(Diagnostic)] #[diag(driver_impl_ice_path_error)] pub(crate) struct IcePathError { - pub path: String, + pub path: std::path::PathBuf, pub error: String, #[subdiagnostic] pub env_var: Option, @@ -67,7 +67,7 @@ pub(crate) struct IcePathError { #[derive(Subdiagnostic)] #[note(driver_impl_ice_path_error_env)] pub(crate) struct IcePathErrorEnv { - pub env_var: String, + pub env_var: std::path::PathBuf, } #[derive(Diagnostic)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index 584b78554ef88..8f8eabb151907 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -162,14 +162,13 @@ fn foo(x: T) { ``` The machine code for `foo::()`, `foo::()`, `foo::()`, or any -other type substitution is different. Hence the compiler generates the +other instantiation is different. Hence the compiler generates the implementation on-demand. If you call `foo()` with a `bool` parameter, the compiler will only generate code for `foo::()`. When we have additional type parameters, the number of monomorphized implementations the compiler generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparameterized substitutions -(i.e., substitutions where none of the substituted types are themselves -parameterized). +implementation if the function is called with fully concrete arguments +(i.e., arguments which do not contain any generic parameters). However, with trait objects we have to make a table containing _every_ object that implements the trait. Now, if it has type parameters, we need to add diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 67a8c3678c5ff..d8c1a3cb55cb5 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -3,7 +3,7 @@ An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: ```compile_fail,E0094 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -18,7 +18,7 @@ and verify with the function declaration in the Rust source code. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 70f14fffae673..19a482f6c93e4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -4,7 +4,7 @@ You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: ```compile_fail -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -41,7 +41,7 @@ impl Foo { For the first code example, please check the function definition. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_error_codes/src/error_codes/E0282.md b/compiler/rustc_error_codes/src/error_codes/E0282.md index 49d2205f92c2a..5de43982e8b28 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0282.md +++ b/compiler/rustc_error_codes/src/error_codes/E0282.md @@ -3,7 +3,7 @@ The compiler could not infer a type and asked for a type annotation. Erroneous code example: ```compile_fail,E0282 -let x = "hello".chars().rev().collect(); +let x = Vec::new(); ``` This error indicates that type inference did not result in one unique possible @@ -11,21 +11,24 @@ type, and extra information is required. In most cases this can be provided by adding a type annotation. Sometimes you need to specify a generic type parameter manually. -A common example is the `collect` method on `Iterator`. It has a generic type -parameter with a `FromIterator` bound, which for a `char` iterator is -implemented by `Vec` and `String` among others. Consider the following snippet -that reverses the characters of a string: +In the example above, type `Vec` has a type parameter `T`. When calling +`Vec::new`, barring any other later usage of the variable `x` that allows the +compiler to infer what type `T` is, the compiler needs to be told what it is. -In the first code example, the compiler cannot infer what the type of `x` should -be: `Vec` and `String` are both suitable candidates. To specify which type -to use, you can use a type annotation on `x`: +The type can be specified on the variable: ``` -let x: Vec = "hello".chars().rev().collect(); +let x: Vec = Vec::new(); ``` -It is not necessary to annotate the full type. Once the ambiguity is resolved, -the compiler can infer the rest: +The type can also be specified in the path of the expression: + +``` +let x = Vec::::new(); +``` + +In cases with more complex types, it is not necessary to annotate the full +type. Once the ambiguity is resolved, the compiler can infer the rest: ``` let x: Vec<_> = "hello".chars().rev().collect(); diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md index 79d2c8204f956..b2f0ede6a0b68 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0283.md +++ b/compiler/rustc_error_codes/src/error_codes/E0283.md @@ -1,7 +1,51 @@ -An implementation cannot be chosen unambiguously because of lack of information. +The compiler could not infer a type and asked for a type annotation. Erroneous code example: +```compile_fail,E0283 +let x = "hello".chars().rev().collect(); +``` + +This error indicates that type inference did not result in one unique possible +type, and extra information is required. In most cases this can be provided +by adding a type annotation. Sometimes you need to specify a generic type +parameter manually. + +A common example is the `collect` method on `Iterator`. It has a generic type +parameter with a `FromIterator` bound, which for a `char` iterator is +implemented by `Vec` and `String` among others. Consider the following snippet +that reverses the characters of a string: + +In the first code example, the compiler cannot infer what the type of `x` should +be: `Vec` and `String` are both suitable candidates. To specify which type +to use, you can use a type annotation on `x`: + +``` +let x: Vec = "hello".chars().rev().collect(); +``` + +It is not necessary to annotate the full type. Once the ambiguity is resolved, +the compiler can infer the rest: + +``` +let x: Vec<_> = "hello".chars().rev().collect(); +``` + +Another way to provide the compiler with enough information, is to specify the +generic type parameter: + +``` +let x = "hello".chars().rev().collect::>(); +``` + +Again, you need not specify the full type if the compiler can infer it: + +``` +let x = "hello".chars().rev().collect::>(); +``` + +We can see a self-contained example below: + ```compile_fail,E0283 struct Foo; diff --git a/compiler/rustc_error_codes/src/error_codes/E0551.md b/compiler/rustc_error_codes/src/error_codes/E0551.md index 53db559a4fcbf..0e078fe71bfd1 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0551.md +++ b/compiler/rustc_error_codes/src/error_codes/E0551.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler + An invalid meta-item was used inside an attribute. Erroneous code example: -```compile_fail,E0551 +```compile_fail,E0539 #[deprecated(note)] // error! fn i_am_deprecated() {} ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0647.md b/compiler/rustc_error_codes/src/error_codes/E0647.md index 8ca6e777f301d..59bb47ba62a9f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0647.md +++ b/compiler/rustc_error_codes/src/error_codes/E0647.md @@ -7,7 +7,7 @@ Erroneous code example: #[start] fn start(_: isize, _: *const *const u8) -> isize where (): Copy { - //^ error: start function is not allowed to have a where clause + //^ error: `#[start]` function is not allowed to have a where clause 0 } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0698.md b/compiler/rustc_error_codes/src/error_codes/E0698.md index 3ba992a8476ed..9bc652e642f6c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0698.md +++ b/compiler/rustc_error_codes/src/error_codes/E0698.md @@ -1,9 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. + When using generators (or async) all type variables must be bound so a generator can be constructed. Erroneous code example: -```edition2018,compile_fail,E0698 +```edition2018,compile_fail,E0282 async fn bar() -> () {} async fn foo() { diff --git a/compiler/rustc_error_codes/src/error_codes/E0760.md b/compiler/rustc_error_codes/src/error_codes/E0760.md index 85e5faada224e..9c4739f0df084 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0760.md +++ b/compiler/rustc_error_codes/src/error_codes/E0760.md @@ -5,7 +5,7 @@ or `Self` that references lifetimes from a parent scope. Erroneous code example: -```compile_fail,edition2018 +```ignore,edition2018 struct S<'a>(&'a i32); impl<'a> S<'a> { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 3fd087b1d5e1e..470f318eb33e3 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -151,7 +151,12 @@ impl fmt::Display for DiagnosticLocation { #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticId { Error(String), - Lint { name: String, has_future_breakage: bool, is_force_warn: bool }, + Lint { + name: String, + /// Indicates whether this lint should show up in cargo's future breakage report. + has_future_breakage: bool, + is_force_warn: bool, + }, } /// A "sub"-diagnostic attached to a parent diagnostic. @@ -301,6 +306,7 @@ impl Diagnostic { } } + /// Indicates whether this diagnostic should show up in cargo's future breakage report. pub fn has_future_breakage(&self) -> bool { match self.code { Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index a170e3a8943ff..4f77f09b26ec4 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -161,7 +161,7 @@ impl IntoDiagnosticArg for hir::ConstContext { DiagnosticArgValue::Str(Cow::Borrowed(match self { hir::ConstContext::ConstFn => "const_fn", hir::ConstContext::Static(_) => "static", - hir::ConstContext::Const => "const", + hir::ConstContext::Const { .. } => "const", })) } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 990bd2d1cc959..665b5d6adec37 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -519,7 +519,7 @@ pub struct HandlerFlags { /// If false, warning-level lints are suppressed. /// (rustc: see `--allow warnings` and `--cap-lints`) pub can_emit_warnings: bool, - /// If true, error-level diagnostics are upgraded to bug-level. + /// If Some, the Nth error-level diagnostic is upgraded to bug-level. /// (rustc: see `-Z treat-err-as-bug`) pub treat_err_as_bug: Option, /// If true, immediately emit diagnostics that would otherwise be buffered. @@ -1376,16 +1376,16 @@ impl HandlerInner { self.emitted_diagnostic_codes.insert(code.clone()); } - let already_emitted = |this: &mut Self| { + let already_emitted = { let mut hasher = StableHasher::new(); diagnostic.hash(&mut hasher); let diagnostic_hash = hasher.finish(); - !this.emitted_diagnostics.insert(diagnostic_hash) + !self.emitted_diagnostics.insert(diagnostic_hash) }; // Only emit the diagnostic if we've been asked to deduplicate or // haven't already emitted an equivalent diagnostic. - if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { + if !(self.flags.deduplicate_diagnostics && already_emitted) { debug!(?diagnostic); debug!(?self.emitted_diagnostics); let already_emitted_sub = |sub: &mut SubDiagnostic| { @@ -1401,6 +1401,11 @@ impl HandlerInner { }; diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); + if already_emitted { + diagnostic.note( + "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`", + ); + } self.emitter.emit_diagnostic(diagnostic); if diagnostic.is_error() { @@ -1719,19 +1724,17 @@ impl HandlerInner { match ( self.err_count() + self.lint_err_count, self.delayed_bug_count(), - self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0), + self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(), ) { (1, 0, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), (0, 1, 1) => panic!("aborting due delayed bug with `-Z treat-err-as-bug=1`"), - (count, delayed_count, as_bug) => { + (count, delayed_count, val) => { if delayed_count > 0 { panic!( - "aborting after {count} errors and {delayed_count} delayed bugs due to `-Z treat-err-as-bug={as_bug}`", + "aborting after {count} errors and {delayed_count} delayed bugs due to `-Z treat-err-as-bug={val}`", ) } else { - panic!( - "aborting after {count} errors due to `-Z treat-err-as-bug={as_bug}`", - ) + panic!("aborting after {count} errors due to `-Z treat-err-as-bug={val}`") } } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 8658cea137a7d..7ad0e799f4464 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -13,17 +13,16 @@ use rustc_ast::NodeId; use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem}; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_feature::{Feature, Features, State as FeatureState}; -use rustc_feature::{ - ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, -}; +use rustc_feature::{ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES}; use rustc_parse::validate_attr; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::{Edition, ALL_EDITIONS}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; +use thin_vec::ThinVec; /// A folder that strips out items that do not belong in the current configuration. pub struct StripUnconfigured<'a> { @@ -37,13 +36,6 @@ pub struct StripUnconfigured<'a> { } pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features { - fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) { - sess.emit_err(FeatureRemoved { - span, - reason: reason.map(|reason| FeatureRemovedReason { reason }), - }); - } - fn active_features_up_to(edition: Edition) -> impl Iterator { ACTIVE_FEATURES.iter().filter(move |feature| { if let Some(feature_edition) = feature.edition { @@ -54,67 +46,49 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features { }) } - let mut features = Features::default(); - let mut edition_enabled_features = FxHashMap::default(); - let crate_edition = sess.edition(); - - for &edition in ALL_EDITIONS { - if edition <= crate_edition { - // The `crate_edition` implies its respective umbrella feature-gate - // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). - edition_enabled_features.insert(edition.feature_name(), edition); + fn feature_list(attr: &Attribute) -> ThinVec { + if attr.has_name(sym::feature) && let Some(list) = attr.meta_item_list() { + list + } else { + ThinVec::new() } } - for feature in active_features_up_to(crate_edition) { - feature.set(&mut features, DUMMY_SP); - edition_enabled_features.insert(feature.name, crate_edition); - } - - // Process the edition umbrella feature-gates first, to ensure - // `edition_enabled_features` is completed before it's queried. - for attr in krate_attrs { - if !attr.has_name(sym::feature) { - continue; - } - - let Some(list) = attr.meta_item_list() else { - continue; - }; - - for mi in list { - if !mi.is_word() { - continue; - } - - let name = mi.name_or_empty(); + let mut features = Features::default(); - let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied(); - if let Some(edition) = edition { - if edition <= crate_edition { - continue; - } + // The edition from `--edition`. + let crate_edition = sess.edition(); - for feature in active_features_up_to(edition) { - // FIXME(Manishearth) there is currently no way to set - // lib features by edition - feature.set(&mut features, DUMMY_SP); - edition_enabled_features.insert(feature.name, edition); + // The maximum of (a) the edition from `--edition` and (b) any edition + // umbrella feature-gates declared in the code. + // - E.g. if `crate_edition` is 2015 but `rust_2018_preview` is present, + // `feature_edition` is 2018 + let mut features_edition = crate_edition; + for attr in krate_attrs { + for mi in feature_list(attr) { + if mi.is_word() { + let name = mi.name_or_empty(); + let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied(); + if let Some(edition) = edition && edition > features_edition { + features_edition = edition; } } } } - for attr in krate_attrs { - if !attr.has_name(sym::feature) { - continue; - } - - let Some(list) = attr.meta_item_list() else { - continue; - }; + // Enable edition-dependent features based on `features_edition`. + // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher + let mut edition_enabled_features = FxHashSet::default(); + for feature in active_features_up_to(features_edition) { + // FIXME(Manishearth) there is currently no way to set lib features by + // edition. + edition_enabled_features.insert(feature.name); + feature.set(&mut features); + } - for mi in list { + // Process all features declared in the code. + for attr in krate_attrs { + for mi in feature_list(attr) { let name = match mi.ident() { Some(ident) if mi.is_word() => ident.name, Some(ident) => { @@ -136,38 +110,59 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features { } }; - if let Some(&edition) = edition_enabled_features.get(&name) { + // If the declared feature is an edition umbrella feature-gate, + // warn if it was redundant w.r.t. `crate_edition`. + // - E.g. warn if `rust_2018_preview` is declared when + // `crate_edition` is 2018 + // - E.g. don't warn if `rust_2018_preview` is declared when + // `crate_edition` is 2015. + if let Some(&edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { + if edition <= crate_edition { + sess.emit_warning(FeatureIncludedInEdition { + span: mi.span(), + feature: name, + edition, + }); + } + features.set_declared_lang_feature(name, mi.span(), None); + continue; + } + + // If the declared feature is edition-dependent and was already + // enabled due to `feature_edition`, give a warning. + // - E.g. warn if `test_2018_feature` is declared when + // `feature_edition` is 2018 or higher. + if edition_enabled_features.contains(&name) { sess.emit_warning(FeatureIncludedInEdition { span: mi.span(), feature: name, - edition, + edition: features_edition, }); + features.set_declared_lang_feature(name, mi.span(), None); continue; } - if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { - // Handled in the separate loop above. - continue; - } - - let removed = REMOVED_FEATURES.iter().find(|f| name == f.name); - let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name); - if let Some(Feature { state, .. }) = removed.or(stable_removed) { - if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } = - state - { - feature_removed(sess, mi.span(), *reason); + // If the declared feature has been removed, issue an error. + if let Some(Feature { state, .. }) = REMOVED_FEATURES.iter().find(|f| name == f.name) { + if let FeatureState::Removed { reason } = state { + sess.emit_err(FeatureRemoved { + span: mi.span(), + reason: reason.map(|reason| FeatureRemovedReason { reason }), + }); continue; } } + // If the declared feature is stable, record it. if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) { let since = Some(Symbol::intern(since)); - features.declared_lang_features.push((name, mi.span(), since)); - features.active_features.insert(name); + features.set_declared_lang_feature(name, mi.span(), since); continue; } + // If `-Z allow-features` is used and the declared feature is + // unstable and not also listed as one of the allowed features, + // issue an error. if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() { if allowed.iter().all(|f| name.as_str() != f) { sess.emit_err(FeatureNotAllowed { span: mi.span(), name }); @@ -175,15 +170,16 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features { } } + // If the declared feature is unstable, record it. if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) { - f.set(&mut features, mi.span()); - features.declared_lang_features.push((name, mi.span(), None)); - features.active_features.insert(name); + f.set(&mut features); + features.set_declared_lang_feature(name, mi.span(), None); continue; } - features.declared_lib_features.push((name, mi.span())); - features.active_features.insert(name); + // Otherwise, the feature is unknown. Record it as a lib feature. + // It will be checked later. + features.set_declared_lib_feature(name, mi.span()); } } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index afcf30d0b293e..32d8380abd3ab 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -197,6 +197,8 @@ declare_features! ( /// + `impl Iterator for &mut Iterator` /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + /// Allows referencing `Self` and projections in impl-trait. + (accepted, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None), /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), /// Allows inferring outlives requirements (RFC 2093). @@ -267,6 +269,8 @@ declare_features! ( (accepted, non_modrs_mods, "1.30.0", Some(44660), None), /// Allows the use of or-patterns (e.g., `0 | 1`). (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows using `+bundle,+whole-archive` link modifiers with native libs. + (accepted, packed_bundled_libs, "CURRENT_RUSTC_VERSION", Some(108081), None), /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. /// This defines the behavior of panics. (accepted, panic_handler, "1.30.0", Some(44489), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f3b88f46baecd..83961647bd442 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -7,15 +7,6 @@ use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -macro_rules! set { - ($field: ident) => {{ - fn f(features: &mut Features, _: Span) { - features.$field = true; - } - f as fn(&mut Features, Span) - }}; -} - #[derive(PartialEq)] enum FeatureStatus { Default, @@ -23,16 +14,19 @@ enum FeatureStatus { Internal, } -macro_rules! declare_features { - (__status_to_enum active) => { +macro_rules! status_to_enum { + (active) => { FeatureStatus::Default }; - (__status_to_enum incomplete) => { + (incomplete) => { FeatureStatus::Incomplete }; - (__status_to_enum internal) => { + (internal) => { FeatureStatus::Internal }; +} + +macro_rules! declare_features { ($( $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr), )+) => { @@ -43,7 +37,10 @@ macro_rules! declare_features { &[$( // (sym::$feature, $ver, $issue, $edition, set!($feature)) Feature { - state: State::Active { set: set!($feature) }, + state: State::Active { + // Sets this feature's corresponding bool within `features`. + set: |features| features.$feature = true, + }, name: sym::$feature, since: $ver, issue: to_nonzero($issue), @@ -58,8 +55,9 @@ macro_rules! declare_features { pub declared_lang_features: Vec<(Symbol, Span, Option)>, /// `#![feature]` attrs for non-language (library) features. pub declared_lib_features: Vec<(Symbol, Span)>, - /// Features enabled for this crate. - pub active_features: FxHashSet, + /// `declared_lang_features` + `declared_lib_features`. + pub declared_features: FxHashSet, + /// Individual features (unstable only). $( $(#[doc = $doc])* pub $feature: bool @@ -67,16 +65,33 @@ macro_rules! declare_features { } impl Features { + pub fn set_declared_lang_feature( + &mut self, + symbol: Symbol, + span: Span, + since: Option + ) { + self.declared_lang_features.push((symbol, span, since)); + self.declared_features.insert(symbol); + } + + pub fn set_declared_lib_feature(&mut self, symbol: Symbol, span: Span) { + self.declared_lib_features.push((symbol, span)); + self.declared_features.insert(symbol); + } + pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) { $(f(stringify!($feature), self.$feature);)+ } - /// Is the given feature active? - pub fn active(&self, feature: Symbol) -> bool { - self.active_features.contains(&feature) + /// Is the given feature explicitly declared, i.e. named in a + /// `#![feature(...)]` within the code? + pub fn declared(&self, feature: Symbol) -> bool { + self.declared_features.contains(&feature) } - /// Is the given feature enabled? + /// Is the given feature enabled, i.e. declared or automatically + /// enabled due to the edition? /// /// Panics if the symbol doesn't correspond to a declared feature. pub fn enabled(&self, feature: Symbol) -> bool { @@ -93,11 +108,10 @@ macro_rules! declare_features { pub fn incomplete(&self, feature: Symbol) -> bool { match feature { $( - sym::$feature => declare_features!(__status_to_enum $status) == FeatureStatus::Incomplete, + sym::$feature => status_to_enum!($status) == FeatureStatus::Incomplete, )* // accepted and removed features aren't in this file but are never incomplete - _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false, - _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false, + _ if self.declared_features.contains(&feature) => false, _ => panic!("`{}` was not listed in `declare_features`", feature), } } @@ -108,12 +122,11 @@ macro_rules! declare_features { pub fn internal(&self, feature: Symbol) -> bool { match feature { $( - sym::$feature => declare_features!(__status_to_enum $status) == FeatureStatus::Internal, + sym::$feature => status_to_enum!($status) == FeatureStatus::Internal, )* // accepted and removed features aren't in this file but are never internal // (a removed feature might have been internal, but it doesn't matter anymore) - _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false, - _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false, + _ if self.declared_features.contains(&feature) => false, _ => panic!("`{}` was not listed in `declare_features`", feature), } } @@ -123,9 +136,9 @@ macro_rules! declare_features { impl Feature { /// Sets this feature in `Features`. Panics if called on a non-active feature. - pub fn set(&self, features: &mut Features, span: Span) { + pub fn set(&self, features: &mut Features) { match self.state { - State::Active { set } => set(features, span), + State::Active { set } => set(features), _ => panic!("called `set` on feature `{}` which is not `active`", self.name), } } @@ -236,15 +249,15 @@ declare_features! ( /// Allows using the `#[fundamental]` attribute. (active, fundamental, "1.0.0", Some(29635), None), /// Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + (internal, link_llvm_intrinsics, "1.0.0", Some(29602), None), /// Allows using the `#[linkage = ".."]` attribute. (active, linkage, "1.0.0", Some(29603), None), /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (internal, needs_panic_runtime, "1.10.0", Some(32837), None), - /// Allows using `+bundled,+whole-archive` native libs. - (active, packed_bundled_libs, "1.69.0", Some(108081), None), /// Allows using the `#![panic_runtime]` attribute. (internal, panic_runtime, "1.10.0", Some(32837), None), + /// Allows `extern "platform-intrinsic" { ... }`. + (internal, platform_intrinsics, "1.4.0", Some(27731), None), /// Allows using `#[rustc_allow_const_fn_unstable]`. /// This is an attribute on `const fn` for the same /// purpose as `#[allow_internal_unstable]`. @@ -470,8 +483,6 @@ declare_features! ( (active, impl_trait_in_assoc_type, "1.70.0", Some(63063), None), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), - /// Allows referencing `Self` and projections in impl-trait. - (active, impl_trait_projections, "1.67.0", Some(103532), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. @@ -526,8 +537,6 @@ declare_features! ( (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), - /// Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), /// Allows using `#![plugin(myplugin)]`. (active, plugin, "1.0.0", Some(29597), None), /// Allows exhaustive integer pattern matching on `usize` and `isize`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 04ebe22a9eb8a..65e697c8f3b80 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -537,7 +537,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ allow_internal_unsafe, Normal, template!(Word), WarnFollowing, "allow_internal_unsafe side-steps the unsafe_code lint", ), - ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk), rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing, "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths"), @@ -667,6 +666,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE ), + // Ensure the argument to this function is &&str during const-check. + rustc_attr!( + rustc_const_panic_str, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Layout related: @@ -806,6 +809,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, r#"`rustc_doc_primitive` is a rustc internal attribute"#, ), + rustc_attr!( + rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, + "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 69e33115922ab..4721bff0ec719 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -23,16 +23,15 @@ mod removed; #[cfg(test)] mod tests; -use rustc_span::{edition::Edition, symbol::Symbol, Span}; +use rustc_span::{edition::Edition, symbol::Symbol}; use std::fmt; use std::num::NonZeroU32; #[derive(Clone, Copy)] pub enum State { Accepted, - Active { set: fn(&mut Features, Span) }, + Active { set: fn(&mut Features) }, Removed { reason: Option<&'static str> }, - Stabilized { reason: Option<&'static str> }, } impl fmt::Debug for State { @@ -41,7 +40,6 @@ impl fmt::Debug for State { State::Accepted { .. } => write!(f, "accepted"), State::Active { .. } => write!(f, "active"), State::Removed { .. } => write!(f, "removed"), - State::Stabilized { .. } => write!(f, "stabilized"), } } } @@ -79,8 +77,8 @@ pub enum UnstableFeatures { impl UnstableFeatures { /// This takes into account `RUSTC_BOOTSTRAP`. /// - /// If `krate` is [`Some`], then setting `RUSTC_BOOTSTRAP=krate` will enable the nightly features. - /// Otherwise, only `RUSTC_BOOTSTRAP=1` will work. + /// If `krate` is [`Some`], then setting `RUSTC_BOOTSTRAP=krate` will enable the nightly + /// features. Otherwise, only `RUSTC_BOOTSTRAP=1` will work. pub fn from_environment(krate: Option<&str>) -> Self { // `true` if this is a feature-staged build, i.e., on the beta or stable channel. let disable_unstable_features = @@ -107,19 +105,17 @@ impl UnstableFeatures { } fn find_lang_feature_issue(feature: Symbol) -> Option { - if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) { - info.issue - } else { - // search in Accepted, Removed, or Stable Removed features - let found = ACCEPTED_FEATURES - .iter() - .chain(REMOVED_FEATURES) - .chain(STABLE_REMOVED_FEATURES) - .find(|t| t.name == feature); - match found { - Some(found) => found.issue, - None => panic!("feature `{feature}` is not declared anywhere"), - } + // Search in all the feature lists. + let found = [] + .iter() + .chain(ACTIVE_FEATURES) + .chain(ACCEPTED_FEATURES) + .chain(REMOVED_FEATURES) + .find(|t| t.name == feature); + + match found { + Some(found) => found.issue, + None => panic!("feature `{feature}` is not declared anywhere"), } } @@ -152,4 +148,4 @@ pub use builtin_attrs::{ is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, }; -pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; +pub use removed::REMOVED_FEATURES; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index da18cb2a239e8..de15deef1789e 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -20,23 +20,6 @@ macro_rules! declare_features { ),+ ]; }; - - ($( - $(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None), - )+) => { - /// Represents stable features which have since been removed (it was once Accepted) - pub const STABLE_REMOVED_FEATURES: &[Feature] = &[ - $( - Feature { - state: State::Stabilized { reason: None }, - name: sym::$feature, - since: $ver, - issue: to_nonzero($issue), - edition: None, - } - ),+ - ]; - }; } #[rustfmt::skip] @@ -141,6 +124,11 @@ declare_features! ( (removed, no_coverage, "CURRENT_RUSTC_VERSION", Some(84605), None, Some("renamed to `coverage_attribute`")), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + /// Note: this feature was previously recorded in a separate + /// `STABLE_REMOVED` list because it, uniquely, was once stable but was + /// then removed. But there was no utility storing it separately, so now + /// it's in this list. + (removed, no_stack_check, "1.0.0", None, None, None), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None, None), @@ -208,8 +196,3 @@ declare_features! ( // feature-group-end: removed features // ------------------------------------------------------------------------- ); - -#[rustfmt::skip] -declare_features! ( - (stable_removed, no_stack_check, "1.0.0", None, None), -); diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 56e23ac277520..7479e4ef2b317 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -40,26 +40,35 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf { } } -/// Tokens to be returned when the macro cannot proceed. -fn failed(crate_name: &Ident) -> proc_macro::TokenStream { +/// Final tokens. +fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream { quote! { - pub static DEFAULT_LOCALE_RESOURCE: &'static str = ""; + /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro, + /// imported by `rustc_driver` to include all crates' resources in one bundle. + pub static DEFAULT_LOCALE_RESOURCE: &'static str = #resource; #[allow(non_upper_case_globals)] #[doc(hidden)] + /// Auto-generated constants for type-checked references to Fluent messages. pub(crate) mod fluent_generated { - pub mod #crate_name { - } + #body + /// Constants expected to exist by the diagnostic derive macros to use as default Fluent + /// identifiers for different subdiagnostic kinds. pub mod _subdiag { + /// Default for `#[help]` pub const help: crate::SubdiagnosticMessage = crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); + /// Default for `#[note]` pub const note: crate::SubdiagnosticMessage = crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); + /// Default for `#[warn]` pub const warn: crate::SubdiagnosticMessage = crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); + /// Default for `#[label]` pub const label: crate::SubdiagnosticMessage = crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); + /// Default for `#[suggestion]` pub const suggestion: crate::SubdiagnosticMessage = crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); } @@ -68,6 +77,11 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream { .into() } +/// Tokens to be returned when the macro cannot proceed. +fn failed(crate_name: &Ident) -> proc_macro::TokenStream { + finish(quote! { pub mod #crate_name {} }, quote! { "" }) +} + /// See [rustc_fluent_macro::fluent_messages]. pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let crate_name = std::env::var("CARGO_PKG_NAME") @@ -311,39 +325,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok } } - quote! { - /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro, - /// imported by `rustc_driver` to include all crates' resources in one bundle. - pub static DEFAULT_LOCALE_RESOURCE: &'static str = include_str!(#relative_ftl_path); - - #[allow(non_upper_case_globals)] - #[doc(hidden)] - /// Auto-generated constants for type-checked references to Fluent messages. - pub(crate) mod fluent_generated { - #constants - - /// Constants expected to exist by the diagnostic derive macros to use as default Fluent - /// identifiers for different subdiagnostic kinds. - pub mod _subdiag { - /// Default for `#[help]` - pub const help: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); - /// Default for `#[note]` - pub const note: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); - /// Default for `#[warn]` - pub const warn: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); - /// Default for `#[label]` - pub const label: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); - /// Default for `#[suggestion]` - pub const suggestion: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); - } - } - } - .into() + finish(constants, quote! { include_str!(#relative_ftl_path) }) } fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> { diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 64271309664ec..3a4eb90f7f963 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -61,9 +61,7 @@ pub enum DefKind { Variant, Trait, /// Type alias: `type Foo = Bar;` - TyAlias { - lazy: bool, - }, + TyAlias, /// Type from an `extern` block. ForeignTy, /// Trait alias: `trait IntIterator = Iterator;` @@ -143,7 +141,7 @@ impl DefKind { DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", DefKind::OpaqueTy => "opaque type", - DefKind::TyAlias { .. } => "type alias", + DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", DefKind::Union => "union", @@ -199,7 +197,7 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -250,7 +248,7 @@ impl DefKind { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cb78da4259702..3eec66611edd1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1581,8 +1581,8 @@ pub enum BodyOwnerKind { /// Closures Closure, - /// Constants and associated constants. - Const, + /// Constants and associated constants, also including inline constants. + Const { inline: bool }, /// Initializer of a `static` item. Static(Mutability), @@ -1592,7 +1592,7 @@ impl BodyOwnerKind { pub fn is_fn_or_closure(self) -> bool { match self { BodyOwnerKind::Fn | BodyOwnerKind::Closure => true, - BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false, + BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false, } } } @@ -1615,7 +1615,7 @@ pub enum ConstContext { /// /// For the most part, other contexts are treated just like a regular `const`, so they are /// lumped into the same category. - Const, + Const { inline: bool }, } impl ConstContext { @@ -1624,7 +1624,7 @@ impl ConstContext { /// E.g. `const` or `static mut`. pub fn keyword_name(self) -> &'static str { match self { - Self::Const => "const", + Self::Const { .. } => "const", Self::Static(Mutability::Not) => "static", Self::Static(Mutability::Mut) => "static mut", Self::ConstFn => "const fn", @@ -1637,7 +1637,7 @@ impl ConstContext { impl fmt::Display for ConstContext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - Self::Const => write!(f, "constant"), + Self::Const { .. } => write!(f, "constant"), Self::Static(_) => write!(f, "static"), Self::ConstFn => write!(f, "constant function"), } @@ -2853,13 +2853,13 @@ impl ImplicitSelfKind { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] #[derive(HashStable_Generic)] pub enum IsAsync { - Async, + Async(Span), NotAsync, } impl IsAsync { pub fn is_async(self) -> bool { - self == IsAsync::Async + matches!(self, IsAsync::Async(_)) } } @@ -3296,7 +3296,7 @@ pub struct FnHeader { impl FnHeader { pub fn is_async(&self) -> bool { - matches!(&self.asyncness, IsAsync::Async) + matches!(&self.asyncness, IsAsync::Async(_)) } pub fn is_const(&self) -> bool { @@ -4091,10 +4091,10 @@ mod size_asserts { static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); - static_assert_size!(ImplItem<'_>, 80); - static_assert_size!(ImplItemKind<'_>, 32); - static_assert_size!(Item<'_>, 80); - static_assert_size!(ItemKind<'_>, 48); + static_assert_size!(ImplItem<'_>, 88); + static_assert_size!(ImplItemKind<'_>, 40); + static_assert_size!(Item<'_>, 88); + static_assert_size!(ItemKind<'_>, 56); static_assert_size!(Local<'_>, 64); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); @@ -4105,8 +4105,8 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - static_assert_size!(TraitItem<'_>, 80); - static_assert_size!(TraitItemKind<'_>, 40); + static_assert_size!(TraitItem<'_>, 88); + static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); // tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 23b20543d5355..4a89a6f7e3926 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -230,7 +230,6 @@ language_item_table! { Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0); PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0); PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; - PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0); PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0); diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 644c4d8265dd5..0d65ddb5642af 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -101,7 +101,7 @@ impl Target { DefKind::Mod => Target::Mod, DefKind::ForeignMod => Target::ForeignMod, DefKind::GlobalAsm => Target::GlobalAsm, - DefKind::TyAlias { .. } => Target::TyAlias, + DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 1160290cdff59..ee475e3de7e99 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -38,6 +38,17 @@ hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present .label = `for<...>` is here +hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures + +hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions + .note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + .coercions_note = currently, {$number} fields need coercions: {$coercions} + .label = requires multiple coercions + +hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}` + +hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found + hir_analysis_const_bound_for_non_const_trait = ~const can only be applied to `#[const_trait]` traits @@ -61,6 +72,15 @@ hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors +hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions + .note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced + .coercions_note = currently, {$number} fields need coercions: {$coercions} + +hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` + +hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + .note = extra field `{$name}` of type `{$ty}` is not allowed + hir_analysis_drop_impl_negative = negative `Drop` impls are not supported hir_analysis_drop_impl_on_wrong_item = @@ -76,8 +96,6 @@ hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed .label = overflowed on value after {$discr} .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome -hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` - hir_analysis_field_already_declared = field `{$field_name}` is already declared .label = field already declared @@ -232,6 +250,8 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures +hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` + hir_analysis_return_type_notation_conflicting_bound = ambiguous associated function `{$assoc_name}` for `{$ty_name}` .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}` @@ -270,20 +290,20 @@ hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is hi hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable .help = add `#![feature(min_specialization)]` to the crate attributes to enable -hir_analysis_start_function_parameters = start function is not allowed to have type parameters - .label = start function cannot have type parameters +hir_analysis_start_function_parameters = `#[start]` function is not allowed to have type parameters + .label = `#[start]` function cannot have type parameters -hir_analysis_start_function_where = start function is not allowed to have a `where` clause - .label = start function cannot have a `where` clause +hir_analysis_start_function_where = `#[start]` function is not allowed to have a `where` clause + .label = `#[start]` function cannot have a `where` clause -hir_analysis_start_not_async = `start` is not allowed to be `async` - .label = `start` is not allowed to be `async` +hir_analysis_start_not_async = `#[start]` function is not allowed to be `async` + .label = `#[start]` is not allowed to be `async` -hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]` - .label = `start` is not allowed to have `#[target_feature]` +hir_analysis_start_not_target_feature = `#[start]` function is not allowed to have `#[target_feature]` + .label = `#[start]` function is not allowed to have `#[target_feature]` -hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]` - .label = `start` is not allowed to be `#[track_caller]` +hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]` + .label = `#[start]` function is not allowed to be `#[track_caller]` hir_analysis_static_specialize = cannot specialize on `'static` lifetime @@ -299,6 +319,9 @@ hir_analysis_too_large_static = extern static is too large for the current archi hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` .suggestion = remove this annotation +hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type + .label = this field does not implement `{$trait_name}` + hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index ba152cd48dea4..21611e9c58600 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -427,7 +427,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(binding.hir_id); ty::Binder::bind_with_vars(subst_output, bound_vars) } else { - // Include substitutions for generic parameters of associated types + // Append the generic arguments of the associated type to the `trait_ref`. candidate.map_bound(|trait_ref| { let ident = Ident::new(assoc_item.name, binding.item_name.span); let item_segment = hir::PathSegment { diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 1372cc896be3f..e3621ef933a52 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -139,22 +139,22 @@ fn generic_arg_mismatch_err( err.emit() } -/// Creates the relevant generic argument substitutions +/// Creates the relevant generic arguments /// corresponding to a set of generic parameters. This is a /// rather complex function. Let us try to explain the role /// of each of its parameters: /// -/// To start, we are given the `def_id` of the thing we are -/// creating the substitutions for, and a partial set of -/// substitutions `parent_args`. In general, the substitutions -/// for an item begin with substitutions for all the "parents" of +/// To start, we are given the `def_id` of the thing whose generic +/// parameters we are instantiating, and a partial set of +/// arguments `parent_args`. In general, the generic arguments +/// for an item begin with arguments for all the "parents" of /// that item -- e.g., for a method it might include the /// parameters from the impl. /// /// Therefore, the method begins by walking down these parents, /// starting with the outermost parent and proceed inwards until /// it reaches `def_id`. For each parent `P`, it will check `parent_args` -/// first to see if the parent's substitutions are listed in there. If so, +/// first to see if the parent's arguments are listed in there. If so, /// we can append those and move on. Otherwise, it invokes the /// three callback functions: /// @@ -188,7 +188,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( stack.push((def_id, parent_defs)); } - // We manually build up the substitution, rather than using convenience + // We manually build up the generic arguments, rather than using convenience // methods in `subst.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); @@ -196,7 +196,8 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( while let Some((def_id, defs)) = stack.pop() { let mut params = defs.params.iter().peekable(); - // If we have already computed substitutions for parents, we can use those directly. + // If we have already computed the generic arguments for parents, + // we can use those directly. while let Some(¶m) = params.peek() { if let Some(&kind) = parent_args.get(param.index as usize) { args.push(kind); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3a97a383ee19e..a91d92313902e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{ 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_span::{sym, BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; @@ -289,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, - /// returns an appropriate set of substitutions for this particular reference to `I`. + /// returns an appropriate set of generic arguments for this particular reference to `I`. pub fn ast_path_args_for_ty( &self, span: Span, @@ -315,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete - /// set of substitutions. This may involve applying defaulted type parameters. + /// set of generic arguments. This may involve applying defaulted type parameters. /// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`. /// /// Example: @@ -909,23 +909,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let args = self.ast_path_args_for_ty(span, did, item_segment); - if let DefKind::TyAlias { lazy: true } = tcx.def_kind(did) { + if let DefKind::TyAlias = tcx.def_kind(did) + && tcx.type_alias_is_lazy(did) + { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. let alias_ty = tcx.mk_alias_ty(did, args); Ty::new_alias(tcx, ty::Weak, alias_ty) } else { - let ty = tcx.at(span).type_of(did); - if ty.skip_binder().has_opaque_types() { - // Type aliases referring to types that contain opaque types (but aren't just directly - // referencing a single opaque type) get encoded as a type alias that normalization will - // then actually instantiate the where bounds of. - let alias_ty = tcx.mk_alias_ty(did, args); - Ty::new_alias(tcx, ty::Weak, alias_ty) - } else { - ty.instantiate(tcx, args) - } + tcx.at(span).type_of(did).instantiate(tcx, args) } } @@ -1282,8 +1275,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return; }; // Get the span of the generics args *including* the leading `::`. - let args_span = - assoc_segment.ident.span.shrink_to_hi().to(args.span_ext); + // We do so by stretching args.span_ext to the left by 2. Earlier + // it was done based on the end of assoc segment but that sometimes + // led to impossible spans and caused issues like #116473 + let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2)); if tcx.generics_of(adt_def.did()).count() == 0 { // FIXME(estebank): we could also verify that the arguments being // work for the `enum`, instead of just looking if it takes *any*. @@ -2164,7 +2159,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Res::Def( DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Struct | DefKind::Union | DefKind::ForeignTy, @@ -2781,7 +2776,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) { for br in referenced_regions.difference(&constrained_regions) { let br_name = match *br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => { + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon | ty::BrEnv => { "an anonymous lifetime".to_string() } ty::BrNamed(_, name) => format!("lifetime `{name}`"), @@ -2789,7 +2784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut err = generate_err(&br_name); - if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br { + if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon = *br { // The only way for an anonymous lifetime to wind up // in the return type but **also** be unconstrained is // if it only appears in "associated types" in the diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 13826264a224c..486aac21972e3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,20 +5,17 @@ use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::Visitor; -use rustc_hir::{ItemKind, Node, PathSegment}; -use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor; +use rustc_hir::Node; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; -use rustc_middle::hir::nested_filter; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::traits::DefiningAnchor; +use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -218,9 +215,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let args = GenericArgs::identity_for_item(tcx, item.owner_id); let span = tcx.def_span(item.owner_id.def_id); - if !tcx.features().impl_trait_projections { - check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); - } if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() { return; } @@ -231,129 +225,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); } -/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result -/// in "inheriting lifetimes". -#[instrument(level = "debug", skip(tcx, span))] -pub(super) fn check_opaque_for_inheriting_lifetimes( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - span: Span, -) { - let item = tcx.hir().expect_item(def_id); - debug!(?item, ?span); - - struct ProhibitOpaqueVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - opaque_identity_ty: Ty<'tcx>, - parent_count: u32, - references_parent_regions: bool, - selftys: Vec<(Span, Option)>, - } - - impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueVisitor<'tcx> { - type BreakTy = Ty<'tcx>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - debug!(?t, "root_visit_ty"); - if t == self.opaque_identity_ty { - ControlFlow::Continue(()) - } else { - t.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, - op: |region| { - if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *region - && index < self.parent_count - { - self.references_parent_regions= true; - } - }, - }); - if self.references_parent_regions { - ControlFlow::Break(t) - } else { - ControlFlow::Continue(()) - } - } - } - } - - impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { - match arg.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { - [PathSegment { res: Res::SelfTyParam { .. }, .. }] => { - let impl_ty_name = None; - self.selftys.push((path.span, impl_ty_name)); - } - [PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => { - let impl_ty_name = Some(self.tcx.def_path_str(*def_id)); - self.selftys.push((path.span, impl_ty_name)); - } - _ => {} - }, - _ => {} - } - hir::intravisit::walk_ty(self, arg); - } - } - - if let ItemKind::OpaqueTy(&hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), - .. - }) = item.kind - { - let args = GenericArgs::identity_for_item(tcx, def_id); - let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - let mut visitor = ProhibitOpaqueVisitor { - opaque_identity_ty, - parent_count: tcx.generics_of(def_id).parent_count as u32, - references_parent_regions: false, - tcx, - selftys: vec![], - }; - let prohibit_opaque = tcx - .explicit_item_bounds(def_id) - .instantiate_identity_iter_copied() - .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); - - if let Some(ty) = prohibit_opaque.break_value() { - visitor.visit_item(&item); - let is_async = match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) - } - _ => unreachable!(), - }; - - let mut err = feature_err( - &tcx.sess.parse_sess, - sym::impl_trait_projections, - span, - format!( - "`{}` return type cannot contain a projection or `Self` that references \ - lifetimes from a parent scope", - if is_async { "async fn" } else { "impl Trait" }, - ), - ); - for (span, name) in visitor.selftys { - err.span_suggestion( - span, - "consider spelling out the type instead", - name.unwrap_or_else(|| format!("{ty:?}")), - Applicability::MaybeIncorrect, - ); - } - err.emit(); - } - } -} - /// Checks that an opaque type does not contain cycles. pub(super) fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, @@ -456,7 +327,7 @@ fn check_opaque_meets_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let guar = infcx.err_ctxt().report_fulfillment_errors(&errors); + let guar = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(guar); } match origin { @@ -640,7 +511,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { check_opaque(tcx, id); } } - DefKind::TyAlias { .. } => { + DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).instantiate_identity(); let generics = tcx.generics_of(id.owner_id); check_type_params_are_used(tcx, &generics, pty_ty); @@ -1579,13 +1450,7 @@ fn opaque_type_cycle_error( label_match(capture.place.ty(), capture.get_path_span(tcx)); } // Label any generator locals that capture the opaque - for interior_ty in - typeck_results.generator_interior_types.as_ref().skip_binder() - { - label_match(interior_ty.ty, interior_ty.span); - } - if tcx.sess.opts.unstable_opts.drop_tracking_mir - && let DefKind::Generator = tcx.def_kind(closure_def_id) + if let DefKind::Generator = tcx.def_kind(closure_def_id) && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id) { for interior_ty in &generator_layout.field_tys { @@ -1603,7 +1468,6 @@ fn opaque_type_cycle_error( } pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { - debug_assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir); debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Generator)); let typeck = tcx.typeck(def_id); @@ -1626,9 +1490,28 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate); fulfillment_cx.register_predicate_obligation(&infcx, obligation); } + + if (tcx.features().unsized_locals || tcx.features().unsized_fn_params) + && let Some(generator) = tcx.mir_generator_witnesses(def_id) + { + for field_ty in generator.field_tys.iter() { + fulfillment_cx.register_bound( + &infcx, + param_env, + field_ty.ty, + tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)), + ObligationCause::new( + field_ty.source_info.span, + def_id, + ObligationCauseCode::SizedGeneratorInterior(def_id), + ), + ); + } + } + let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); } } 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 38f19aa09adf4..f1514ecf69c1f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -14,7 +14,9 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{ self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -321,7 +323,7 @@ fn compare_method_predicate_entailment<'tcx>( // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed. let errors = ocx.select_where_possible(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } @@ -392,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>( }); } CheckImpliedWfMode::Skip => { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } } @@ -595,7 +597,7 @@ fn compare_asyncness<'tcx>( trait_m: ty::AssocItem, delay: bool, ) -> Result<(), ErrorGuaranteed> { - if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async { + if tcx.asyncness(trait_m.def_id).is_async() { match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() { ty::Alias(ty::Opaque, ..) => { // allow both `async fn foo()` and `fn foo() -> impl Future` @@ -661,8 +663,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity(); - let param_env = tcx.param_env(impl_m_def_id); - // First, check a few of the same things as `compare_impl_method`, // just so we don't ICE during substitution later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; @@ -688,13 +688,26 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_to_placeholder_args = impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args); + let hybrid_preds = tcx + .predicates_of(impl_m.container_id(tcx)) + .instantiate_identity(tcx) + .into_iter() + .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args)) + .map(|(clause, _)| clause); + let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); + let param_env = traits::normalize_param_env_or_error( + tcx, + param_env, + ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id), + ); + let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); // Normalize the impl signature with fresh variables for lifetime inference. - let norm_cause = ObligationCause::misc(return_span, impl_m_def_id); + let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); let impl_sig = ocx.normalize( - &norm_cause, + &misc_cause, param_env, tcx.liberate_late_bound_regions( impl_m.def_id, @@ -725,12 +738,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ); } - let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig); + let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig); trait_sig.error_reported()?; let trait_return_ty = trait_sig.output(); + // RPITITs are allowed to use the implied predicates of the method that + // defines them. This is because we want code like: + // ``` + // trait Foo { + // fn test<'a, T>(_: &'a T) -> impl Sized; + // } + // impl Foo for () { + // fn test<'a, T>(x: &'a T) -> &'a T { x } + // } + // ``` + // .. to compile. However, since we use both the normalized and unnormalized + // inputs and outputs from the substituted trait signature, we will end up + // seeing the hidden type of an RPIT in the signature itself. Naively, this + // means that we will use the hidden type to imply the hidden type's own + // well-formedness. + // + // To avoid this, we replace the infer vars used for hidden type inference + // with placeholders, which imply nothing about outlives bounds, and then + // prove below that the hidden types are well formed. + let universe = infcx.create_next_universe(); + let mut idx = 0; + let mapping: FxHashMap<_, _> = collector + .types + .iter() + .map(|(_, &(ty, _))| { + assert!( + infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(), + "{ty:?} should not have been constrained via normalization", + ty = infcx.resolve_vars_if_possible(ty) + ); + idx += 1; + ( + ty, + Ty::new_placeholder( + tcx, + ty::Placeholder { + universe, + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(idx), + kind: ty::BoundTyKind::Anon, + }, + }, + ), + ) + }) + .collect(); + let mut type_mapper = BottomUpFolder { + tcx, + ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty), + lt_op: |lt| lt, + ct_op: |ct| ct, + }; let wf_tys = FxIndexSet::from_iter( - unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()), + unnormalized_trait_sig + .inputs_and_output + .iter() + .chain(trait_sig.inputs_and_output.iter()) + .map(|ty| ty.fold_with(&mut type_mapper)), ); match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) { @@ -787,16 +856,28 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( } } + // FIXME: This has the same issue as #108544, but since this isn't breaking + // existing code, I'm not particularly inclined to do the same hack as above + // where we process wf obligations manually. This can be fixed in a forward- + // compatible way later. + let collected_types = collector.types; + for (_, &(ty, _)) in &collected_types { + ocx.register_obligation(traits::Obligation::new( + tcx, + misc_cause.clone(), + param_env, + ty::ClauseKind::WellFormed(ty.into()), + )); + } + // Check that all obligations are satisfied by the implementation's // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } - let collected_types = collector.types; - // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( @@ -1108,7 +1189,7 @@ fn report_trait_method_mismatch<'tcx>( let ap = Applicability::MachineApplicable; match sig.decl.output { hir::FnRetTy::DefaultReturn(sp) => { - let sugg = format!("-> {} ", trait_sig.output()); + let sugg = format!(" -> {}", trait_sig.output()); diag.span_suggestion_verbose(sp, msg, sugg, ap); } hir::FnRetTy::Return(hir_ty) => { @@ -1134,7 +1215,10 @@ fn report_trait_method_mismatch<'tcx>( &mut diag, &cause, trait_err_span.map(|sp| (sp, Cow::from("type in trait"))), - Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })), + Some(infer::ValuePairs::PolySigs(ExpectedFound { + expected: ty::Binder::dummy(trait_sig), + found: ty::Binder::dummy(impl_sig), + })), terr, false, false, @@ -1966,7 +2050,7 @@ fn compare_const_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - return Err(infcx.err_ctxt().report_fulfillment_errors(&errors)); + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } let outlives_env = OutlivesEnvironment::new(param_env); @@ -2059,7 +2143,7 @@ fn compare_type_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } @@ -2196,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>( // // impl X for T where T: X { type Y = ::Y; } } - _ => predicates.push(ty::Clause::from_projection_clause( - tcx, + _ => predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args), term: normalize_impl_ty.into(), }, bound_vars, - ), - )), + ) + .to_predicate(tcx), + ), }; ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing) }; @@ -2274,7 +2358,7 @@ pub(super) fn check_type_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index a8149b634ef7c..bc5029a1d5e47 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt}; use rustc_lint_defs::builtin::REFINING_IMPL_TRAIT; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::{ @@ -23,8 +23,12 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) { return; } - // crate-private traits don't have any library guarantees, there's no need to do this check. - if !tcx.visibility(trait_m.container_id(tcx)).is_public() { + // unreachable traits don't have any library guarantees, there's no need to do this check. + if trait_m + .container_id(tcx) + .as_local() + .is_some_and(|trait_def_id| !tcx.effective_visibilities(()).is_reachable(trait_def_id)) + { return; } @@ -176,9 +180,13 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; - // For quicker lookup, use an `IndexSet` - // (we don't use one earlier because it's not foldable..) - let trait_bounds = FxIndexSet::from_iter(trait_bounds); + // For quicker lookup, use an `IndexSet` (we don't use one earlier because + // it's not foldable..). + // Also, We have to anonymize binders in these types because they may contain + // `BrNamed` bound vars, which contain unique `DefId`s which correspond to syntax + // locations that we don't care about when checking bound equality. + let trait_bounds = FxIndexSet::from_iter(trait_bounds.fold_with(&mut Anonymize { tcx })); + let impl_bounds = impl_bounds.fold_with(&mut Anonymize { tcx }); // Find any clauses that are present in the impl's RPITITs that are not // present in the trait's RPITITs. This will trigger on trivial predicates, @@ -309,3 +317,20 @@ fn type_visibility<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option None, } } + +struct Anonymize<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeFolder> for Anonymize<'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + where + T: TypeFoldable>, + { + self.tcx.anonymize_bound_vars(t) + } +} diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index fcaefe0261b0b..6681292c93d13 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -11,8 +11,8 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use std::ops::Not; +use super::check_function_signature; use crate::errors; -use crate::require_same_types; pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) { match tcx.entry_fn(()) { @@ -112,7 +112,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } let main_asyncness = tcx.asyncness(main_def_id); - if let hir::IsAsync::Async = main_asyncness { + if main_asyncness.is_async() { let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span }); error = true; @@ -158,37 +158,37 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); error = true; } // now we can take the return type of the given main function - expected_return_type = main_fnsig.output(); + expected_return_type = norm_return_ty; } else { // standard () main return type - expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx)); + expected_return_type = tcx.types.unit; } if error { return; } - 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) - }), - ); + let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( + [], + expected_return_type, + false, + hir::Unsafety::Normal, + Abi::Rust, + )); - require_same_types( + check_function_signature( tcx, - &ObligationCause::new( + ObligationCause::new( main_span, main_diagnostics_def_id, ObligationCauseCode::MainFunctionType, ), - param_env, - se_ty, - Ty::new_fn_ptr(tcx, main_fnsig), + main_def_id, + expected_sig, ); } @@ -212,7 +212,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { }); error = true; } - if let hir::IsAsync::Async = sig.header.asyncness { + if sig.header.asyncness.is_async() { let span = tcx.def_span(it.owner_id); tcx.sess.emit_err(errors::StartAsync { span: span }); error = true; @@ -247,27 +247,23 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } } - 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, - )), - ); + let expected_sig = 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( + check_function_signature( tcx, - &ObligationCause::new( + ObligationCause::new( start_span, start_def_id, ObligationCauseCode::StartFunctionType, ), - ty::ParamEnv::empty(), // start should not have any where bounds. - se_ty, - Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()), + start_def_id.into(), + expected_sig, ); } _ => { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index f89e2e5c25bf2..c61719c1fd293 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,11 +1,11 @@ //! Type-checking for the rust-intrinsic and platform-intrinsic //! intrinsics that the compiler exposes. +use crate::check::check_function_signature; use crate::errors::{ UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic, }; -use crate::require_same_types; use hir::def_id::DefId; use rustc_errors::{struct_span_err, DiagnosticMessage}; @@ -20,6 +20,7 @@ fn equate_intrinsic_type<'tcx>( it: &hir::ForeignItem<'_>, n_tps: usize, n_lts: usize, + n_cts: usize, sig: ty::PolyFnSig<'tcx>, ) { let (own_counts, span) = match &it.kind { @@ -51,17 +52,14 @@ fn equate_intrinsic_type<'tcx>( if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") && gen_count_ok(own_counts.types, n_tps, "type") - && gen_count_ok(own_counts.consts, 0, "const") + && gen_count_ok(own_counts.consts, n_cts, "const") { - 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( + check_function_signature( tcx, - &cause, - ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env? - Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()), - fty, + ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType), + it_def_id.into(), + sig, ); } } @@ -140,7 +138,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds(&[ - ty::BoundVariableKind::Region(ty::BrAnon(None)), + ty::BoundVariableKind::Region(ty::BrAnon), ty::BoundVariableKind::Region(ty::BrEnv), ]); let mk_va_list_ty = |mutbl| { @@ -148,7 +146,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let region = ty::Region::new_late_bound( tcx, ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, ); let env_region = ty::Region::new_late_bound( tcx, @@ -408,7 +406,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ); let discriminant_def_id = assoc_items[0]; - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; ( 1, vec![Ty::new_imm_ref( @@ -466,7 +464,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } sym::raw_eq => { - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; let param_ty = Ty::new_imm_ref( tcx, ty::Region::new_late_bound(tcx, ty::INNERMOST, br), @@ -492,7 +490,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }; let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, 0, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -504,9 +502,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) let name = it.ident.name; - let (n_tps, inputs, output) = match name { + let (n_tps, n_cts, inputs, output) = match name { sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => { - (2, vec![param(0), param(0)], param(1)) + (2, 0, vec![param(0), param(0)], param(1)) } sym::simd_add | sym::simd_sub @@ -522,8 +520,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fmax | sym::simd_fpow | sym::simd_saturating_add - | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), - sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)), + | sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)), + sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)), sym::simd_neg | sym::simd_bswap | sym::simd_bitreverse @@ -541,25 +539,25 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_ceil | sym::simd_floor | sym::simd_round - | sym::simd_trunc => (1, vec![param(0)], param(0)), - 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)], 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_trunc => (1, 0, vec![param(0)], param(0)), + sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)), + sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), + sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), + sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), + sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), + sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), sym::simd_cast | sym::simd_as | sym::simd_cast_ptr | sym::simd_expose_addr - | sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)), - sym::simd_bitmask => (2, vec![param(0)], param(1)), + | sym::simd_from_exposed_addr => (2, 0, vec![param(0)], param(1)), + sym::simd_bitmask => (2, 0, vec![param(0)], param(1)), sym::simd_select | sym::simd_select_bitmask => { - (2, vec![param(0), param(1), param(1)], param(1)) + (2, 0, vec![param(0), param(1), param(1)], param(1)) } - sym::simd_reduce_all | sym::simd_reduce_any => (1, vec![param(0)], tcx.types.bool), + sym::simd_reduce_all | sym::simd_reduce_any => (1, 0, vec![param(0)], tcx.types.bool), sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => { - (2, vec![param(0), param(1)], param(1)) + (2, 0, vec![param(0), param(1)], param(1)) } sym::simd_reduce_add_unordered | sym::simd_reduce_mul_unordered @@ -569,8 +567,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_min | sym::simd_reduce_max | sym::simd_reduce_min_nanless - | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), - sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), + | sym::simd_reduce_max_nanless => (2, 0, vec![param(0)], param(1)), + sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)), + sym::simd_shuffle_generic => (2, 1, vec![param(0), param(0)], param(1)), _ => { let msg = format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, msg).emit(); @@ -580,5 +579,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, 0, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, n_cts, sig) } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d833166136669..5d67a36288c63 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -73,23 +73,31 @@ pub mod wfcheck; pub use check::check_abi; +use std::num::NonZeroU32; + use check::check_mod_item_types; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::BitSet; +use rustc_infer::infer::error_reporting::ObligationCauseExt as _; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{self, TyCtxtInferExt as _}; +use rustc_infer::traits::ObligationCause; use rustc_middle::query::Providers; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::parse::feature_err; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{self, BytePos, Span, Symbol}; +use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; -use std::num::NonZeroU32; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; +use rustc_trait_selection::traits::ObligationCtxt; use crate::errors; use crate::require_c_abi_if_c_variadic; @@ -321,41 +329,52 @@ fn bounds_from_generic_predicates<'tcx>( _ => {} } } - let generics = if types.is_empty() { - "".to_string() - } else { - format!( - "<{}>", - types - .keys() - .filter_map(|t| match t.kind() { - ty::Param(_) => Some(t.to_string()), - // Avoid suggesting the following: - // fn foo::Bar>(_: T) where T: Trait, ::Bar: Other {} - _ => None, - }) - .collect::>() - .join(", ") - ) - }; + let mut where_clauses = vec![]; + let mut types_str = vec![]; for (ty, bounds) in types { - where_clauses - .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound)))); - } - for projection in &projections { - let p = projection.skip_binder(); - // FIXME: this is not currently supported syntax, we should be looking at the `types` and - // insert the associated types where they correspond, but for now let's be "lazy" and - // propose this instead of the following valid resugaring: - // `T: Trait, Trait::Assoc = K` → `T: Trait` - where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term)); + if let ty::Param(_) = ty.kind() { + let mut bounds_str = vec![]; + for bound in bounds { + let mut projections_str = vec![]; + for projection in &projections { + let p = projection.skip_binder(); + let alias_ty = p.projection_ty; + if bound == tcx.parent(alias_ty.def_id) && alias_ty.self_ty() == ty { + let name = tcx.item_name(alias_ty.def_id); + projections_str.push(format!("{} = {}", name, p.term)); + } + } + let bound_def_path = tcx.def_path_str(bound); + if projections_str.is_empty() { + where_clauses.push(format!("{}: {}", ty, bound_def_path)); + } else { + bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", "))); + } + } + if bounds_str.is_empty() { + types_str.push(ty.to_string()); + } else { + types_str.push(format!("{}: {}", ty, bounds_str.join(" + "))); + } + } else { + // Avoid suggesting the following: + // fn foo::Bar>(_: T) where T: Trait, ::Bar: Other {} + where_clauses.extend( + bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))), + ); + } } + + let generics = + if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) }; + let where_clauses = if where_clauses.is_empty() { - String::new() + "".to_string() } else { format!(" where {}", where_clauses.join(", ")) }; + (generics, where_clauses) } @@ -546,3 +565,76 @@ fn bad_non_zero_sized_fields<'tcx>( pub fn potentially_plural_count(count: usize, word: &str) -> String { format!("{} {}{}", count, word, pluralize!(count)) } + +pub fn check_function_signature<'tcx>( + tcx: TyCtxt<'tcx>, + mut cause: ObligationCause<'tcx>, + fn_id: DefId, + expected_sig: ty::PolyFnSig<'tcx>, +) { + let local_id = fn_id.as_local().unwrap_or(CRATE_DEF_ID); + + let param_env = ty::ParamEnv::empty(); + + let infcx = &tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(infcx); + + let actual_sig = tcx.fn_sig(fn_id).instantiate_identity(); + + let norm_cause = ObligationCause::misc(cause.span, local_id); + let actual_sig = ocx.normalize(&norm_cause, param_env, actual_sig); + + match ocx.eq(&cause, param_env, expected_sig, actual_sig) { + Ok(()) => { + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(errors); + return; + } + } + Err(err) => { + let err_ctxt = infcx.err_ctxt(); + if fn_id.is_local() { + cause.span = extract_span_for_error_reporting(tcx, err, &cause, local_id); + } + let failure_code = cause.as_failure_code_diag(err, cause.span, vec![]); + let mut diag = tcx.sess.create_err(failure_code); + err_ctxt.note_type_err( + &mut diag, + &cause, + None, + Some(infer::ValuePairs::PolySigs(ExpectedFound { + expected: expected_sig, + found: actual_sig, + })), + err, + false, + false, + ); + diag.emit(); + return; + } + } + + let outlives_env = OutlivesEnvironment::new(param_env); + let _ = ocx.resolve_regions_and_report_errors(local_id, &outlives_env); + + fn extract_span_for_error_reporting<'tcx>( + tcx: TyCtxt<'tcx>, + err: TypeError<'_>, + cause: &ObligationCause<'tcx>, + fn_id: LocalDefId, + ) -> rustc_span::Span { + let mut args = { + let node = tcx.hir().expect_owner(fn_id); + let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); + decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) + }; + + match err { + TypeError::ArgumentMutability(i) + | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => args.nth(i).unwrap(), + _ => cause.span(), + } + } +} diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b97e0a80fe6c9..97ebd42d0778a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,6 +24,9 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; +use rustc_trait_selection::traits::misc::{ + type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, +}; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ @@ -113,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let errors = wfcx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); return; } @@ -246,9 +249,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::TyAlias(hir_ty, ast_generics) => { - if tcx.features().lazy_type_alias - || tcx.type_of(item.owner_id).skip_binder().has_opaque_types() - { + if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); @@ -867,43 +868,65 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { ); }); } else { - let err_ty_str; - let mut is_ptr = true; - - let err = match ty.kind() { + let diag = match ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None, - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => { - is_ptr = false; - err_ty_str = format!("`{ty}`"); - Some(err_ty_str.as_str()) - } + ty::FnPtr(_) => Some(tcx.sess.struct_span_err( + hir_ty.span, + "using function pointers as const generic parameters is forbidden", + )), + ty::RawPtr(_) => Some(tcx.sess.struct_span_err( + hir_ty.span, + "using raw pointers as const generic parameters is forbidden", + )), + _ => Some(tcx.sess.struct_span_err( + hir_ty.span, + format!("`{}` is forbidden as the type of a const generic parameter", ty), + )), }; - if let Some(unsupported_type) = err { - if is_ptr { - tcx.sess.span_err( - hir_ty.span, - format!( - "using {unsupported_type} as const generic parameters is forbidden", - ), - ); - } else { - let mut err = tcx.sess.struct_span_err( - hir_ty.span, - format!( - "{unsupported_type} is forbidden as the type of a const generic parameter", - ), - ); - err.note("the only supported types are integers, `bool` and `char`"); - if tcx.sess.is_nightly_build() { - err.help( - "more complex types are supported with `#![feature(adt_const_params)]`", - ); + if let Some(mut diag) = diag { + diag.note("the only supported types are integers, `bool` and `char`"); + + let cause = ObligationCause::misc(hir_ty.span, param.def_id); + let may_suggest_feature = match type_allowed_to_implement_const_param_ty( + tcx, + tcx.param_env(param.def_id), + ty, + cause, + ) { + // Can never implement `ConstParamTy`, don't suggest anything. + Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false, + // May be able to implement `ConstParamTy`. Only emit the feature help + // if the type is local, since the user may be able to fix the local type. + Err(ConstParamTyImplementationError::InfrigingFields(..)) => { + fn ty_is_local(ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Adt(adt_def, ..) => adt_def.did().is_local(), + // Arrays and slices use the inner type's `ConstParamTy`. + ty::Array(ty, ..) => ty_is_local(*ty), + ty::Slice(ty) => ty_is_local(*ty), + // `&` references use the inner type's `ConstParamTy`. + // `&mut` are not supported. + ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty), + // Say that a tuple is local if any of its components are local. + // This is not strictly correct, but it's likely that the user can fix the local component. + ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)), + _ => false, + } + } + + ty_is_local(ty) } - err.emit(); + // Implments `ConstParamTy`, suggest adding the feature to enable. + Ok(..) => true, + }; + if may_suggest_feature && tcx.sess.is_nightly_build() { + diag.help( + "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types", + ); } + + diag.emit(); } } } @@ -1107,11 +1130,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt let wf_obligations = bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| { let normalized_bound = wfcx.normalize(span, None, bound); - traits::wf::predicate_obligations( + traits::wf::clause_obligations( wfcx.infcx, wfcx.param_env, wfcx.body_def_id, - normalized_bound.as_predicate(), + normalized_bound, bound_span, ) }); @@ -1211,7 +1234,7 @@ fn check_impl<'tcx>( wfcx.infcx, wfcx.param_env, wfcx.body_def_id, - &trait_pred, + trait_pred, ast_trait_ref.path.span, item, ); @@ -1420,13 +1443,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id debug!(?predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| { - traits::wf::predicate_obligations( - infcx, - wfcx.param_env, - wfcx.body_def_id, - p.as_predicate(), - sp, - ) + traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp) }); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); wfcx.register_obligations(obligations); @@ -1711,10 +1728,8 @@ fn check_variances_for_type_defn<'tcx>( } } ItemKind::TyAlias(..) => { - let ty = tcx.type_of(item.owner_id).instantiate_identity(); - - if tcx.features().lazy_type_alias || ty.has_opaque_types() { - if ty.references_error() { + if tcx.type_alias_is_lazy(item.owner_id) { + if tcx.type_of(item.owner_id).skip_binder().references_error() { return; } } else { @@ -1755,6 +1770,8 @@ fn check_variances_for_type_defn<'tcx>( .collect::>() }); + let ty_generics = tcx.generics_of(item.owner_id); + for (index, _) in variances.iter().enumerate() { let parameter = Parameter(index as u32); @@ -1762,13 +1779,27 @@ fn check_variances_for_type_defn<'tcx>( continue; } - let param = &hir_generics.params[index]; + let ty_param = &ty_generics.params[index]; + let hir_param = &hir_generics.params[index]; + + if ty_param.def_id != hir_param.def_id.into() { + // valid programs always have lifetimes before types in the generic parameter list + // ty_generics are normalized to be in this required order, and variances are built + // from ty generics, not from hir generics. but we need hir generics to get + // a span out + // + // if they aren't in the same order, then the user has written invalid code, and already + // got an error about it (or I'm wrong about this) + tcx.sess + .delay_span_bug(hir_param.span, "hir generics and ty generics in different order"); + continue; + } - match param.name { + match hir_param.name { hir::ParamName::Error => {} _ => { let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); - report_bivariance(tcx, param, has_explicit_bounds); + report_bivariance(tcx, hir_param, has_explicit_bounds); } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 94f3e8706fce3..e3e724df27227 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,11 +1,10 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use crate::errors::{ - ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem, -}; +use crate::errors; + use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let impl_ = tcx.hir().expect_item(impl_did).expect_impl(); - tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span }); + tcx.sess.emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { @@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span); } Err(CopyImplementationError::NotAnAdt) => { - tcx.sess.emit_err(CopyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::CopyImplOnNonAdt { span }); } Err(CopyImplementationError::HasDestructor) => { - tcx.sess.emit_err(CopyImplOnTypeWithDtor { span }); + tcx.sess.emit_err(errors::CopyImplOnTypeWithDtor { span }); } } } @@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span); } Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { - tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::ConstParamTyImplOnNonAdt { span }); } } } @@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let param_env = tcx.param_env(impl_did); - let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg); - let infcx = tcx.infer_ctxt().build(); let cause = ObligationCause::misc(span, impl_did); @@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - create_err(&format!( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{source_path}`, found `{target_path}`", - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynCoercion { + span, + trait_name: "DispatchFromDyn", + note: true, + source_path, + target_path, + }); return; } if def_a.repr().c() || def_a.repr().packed() { - create_err( - "structs implementing `DispatchFromDyn` may not have \ - `#[repr(packed)]` or `#[repr(C)]`", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynRepr { span }); } let fields = &def_a.non_enum_variant().fields; @@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) { if ok.obligations.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for structs containing the field being coerced, \ - ZST fields with 1 byte alignment, and nothing else", - ) - .note(format!( - "extra field `{}` of type `{}` is not allowed", - field.name, ty_a, - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynZST { + span, + name: field.name, + ty: ty_a, + }); return false; } @@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef .collect::>(); if coerced_fields.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced, none found", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynSingle { + span, + trait_name: "DispatchFromDyn", + note: true, + }); } else if coerced_fields.len() > 1 { - create_err("implementing the `DispatchFromDyn` trait requires multiple coercions") - .note( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - coerced_fields.len(), - coerced_fields - .iter() - .map(|field| { - format!( - "`{}` (`{}` to `{}`)", - field.name, - field.ty(tcx, args_a), - field.ty(tcx, args_b), - ) - }) - .collect::>() - .join(", ") - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynMulti { + span, + coercions_note: true, + number: coerced_fields.len(), + coercions: coerced_fields + .iter() + .map(|field| { + format!( + "`{}` (`{}` to `{}`)", + field.name, + field.ty(tcx, args_a), + field.ty(tcx, args_b), + ) + }) + .collect::>() + .join(", "), + }); } else { let ocx = ObligationCtxt::new(&infcx); for field in coerced_fields { @@ -279,7 +261,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); } // Finally, resolve all regions. @@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } _ => { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures", - ) - .emit(); + tcx.sess.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" }); } } } @@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe if def_a != def_b { let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::DispatchFromDynSame { span, - E0377, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{}`, found `{}`", + trait_name: "CoerceUnsized", + note: true, source_path, - target_path - ) - .emit(); + target_path, + }); return err_info; } @@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe .collect::>(); if diff_fields.is_empty() { - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedOneField { span, - E0374, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with one field \ - being coerced, none found" - ) - .emit(); + trait_name: "CoerceUnsized", + note: true, + }); return err_info; } else if diff_fields.len() > 1 { let item = tcx.hir().expect_item(impl_did); @@ -463,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe tcx.def_span(impl_did) }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedMulti { span, - E0375, - "implementing the trait \ - `CoerceUnsized` requires multiple \ - coercions" - ) - .note( - "`CoerceUnsized` may only be implemented for \ - a coercion between structures with one field being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - diff_fields.len(), - diff_fields + coercions_note: true, + number: diff_fields.len(), + coercions: diff_fields .iter() - .map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) }) + .map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b)) .collect::>() - .join(", ") - )) - .span_label(span, "requires multiple coercions") - .emit(); + .join(", "), + }); + return err_info; } @@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe } _ => { - struct_span_err!( - tcx.sess, - span, - E0376, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures" - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" }); return err_info; } }; @@ -519,7 +470,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); } // Finally, resolve all regions. @@ -540,13 +491,6 @@ fn infringing_fields_error( let trait_name = tcx.def_path_str(trait_did); - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0204, - "the trait `{trait_name}` cannot be implemented for this type" - ); - // We'll try to suggest constraining type parameters to fulfill the requirements of // their `Copy` implementation. let mut errors: BTreeMap<_, Vec<_>> = Default::default(); @@ -554,14 +498,15 @@ fn infringing_fields_error( let mut seen_tys = FxHashSet::default(); + let mut label_spans = Vec::new(); + for (field, ty, reason) in fields { // Only report an error once per type. if !seen_tys.insert(ty) { continue; } - let field_span = tcx.def_span(field.did); - err.span_label(field_span, format!("this field does not implement `{trait_name}`")); + label_spans.push(tcx.def_span(field.did)); match reason { InfringingFieldsReason::Fulfill(fulfillment_errors) => { @@ -625,13 +570,24 @@ fn infringing_fields_error( } } } + let mut notes = Vec::new(); for ((ty, error_predicate), spans) in errors { let span: MultiSpan = spans.into(); - err.span_note( + notes.push(errors::ImplForTyRequires { span, - format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"), - ); + error_predicate, + trait_name: trait_name.clone(), + ty, + }); } + + let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy { + span: impl_span, + trait_name, + label_spans, + notes, + }); + suggest_constraining_type_params( tcx, tcx.hir().get_generics(impl_did).expect("impls always have generics"), diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index aa7c9e504c1a9..0042d683b1913 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -157,7 +157,6 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index bbdb108c59b63..69020b1f11dc6 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -245,7 +245,6 @@ fn do_orphan_check_impl<'tcx>( ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 01e40c62a8bff..221df4e36b296 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -58,6 +58,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { type_of: type_of::type_of, type_of_opaque: type_of::type_of_opaque, + type_alias_is_lazy: type_of::type_alias_is_lazy, item_bounds: item_bounds::item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds, generics_of: generics_of::generics_of, @@ -1373,7 +1374,7 @@ fn impl_trait_ref( // make astconv happy. let mut path_segments = ast_trait_ref.path.segments.to_vec(); let last_segment = path_segments.len() - 1; - let mut args = path_segments[last_segment].args().clone(); + let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host))); args.args = &args.args[..args.args.len() - 1]; diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c4d053c5d9f49..7c1a6420305ed 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -94,12 +94,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // ^ param_id // ^^^ parent_id after twice iterations // ^ generics of parent - // Push GenericParamDef of 'N' in above example into params. + // Push GenericParamDef 'N' into params. if let hir::Node::GenericParam( GenericParam{ - hir_id: parent_hir_id, + hir_id: _hir_id, kind: GenericParamKind::Const { - ty: ty_info, + ty: _ty, default: Some(anon_const) }, name, def_id, @@ -127,6 +127,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { host_effect_index: None, }; } + let param_def_idx = generics.param_def_id_to_index[¶m_id.to_def_id()]; // In the above example this would be .params[..N#0] let params = generics.params_to(param_def_idx as usize, tcx).to_owned(); 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 e9aac2bfbc86a..b1ad4f30d151c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -859,22 +859,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { walk_list!(this, visit_generic_param, generics.params); - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { default, .. } => { - if let Some(ty) = default { - this.visit_ty(ty); - } - } - GenericParamKind::Const { ty, default } => { - this.visit_ty(ty); - if let Some(default) = default { - this.visit_body(this.tcx.hir().body(default.body)); - } - } - } - } walk_list!(this, visit_where_predicate, generics.predicates); }) } @@ -996,7 +980,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) { match p.kind { - GenericParamKind::Const { ty, default: Some(default) } => { + GenericParamKind::Const { ty: _, default: Some(default) } => { self.resolve_type_ref(p.def_id, p.hir_id); // For expr in default of Const expr in where predict. @@ -1024,6 +1008,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // like implicit `?Sized` or const-param-has-ty predicates. } } + + match p.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { default, .. } => { + if let Some(ty) = default { + self.visit_ty(ty); + } + } + GenericParamKind::Const { ty, default } => { + self.visit_ty(ty); + if let Some(default) = default { + self.visit_body(self.tcx.hir().body(default.body)); + } + } + } } } @@ -1239,7 +1238,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id)) && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) && param.is_elided_lifetime() - && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) + && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async() && !self.tcx.features().anonymous_lifetime_in_impl_trait { let mut diag = rustc_session::parse::feature_err( @@ -1545,7 +1544,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Trait, def_id, ) if depth == 0 => Some(def_id), @@ -2055,7 +2054,7 @@ fn is_late_bound_map( hir::TyKind::Path(hir::QPath::Resolved( None, - hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span }, + hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, )) => { // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider // args to be unconstrained. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d12337687e2e1..ae62119b1825f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -623,3 +623,25 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { .emit(); } } + +pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + use hir::intravisit::Visitor; + if tcx.features().lazy_type_alias { + return true; + } + struct HasTait { + has_type_alias_impl_trait: bool, + } + impl<'tcx> Visitor<'tcx> for HasTait { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + if let hir::TyKind::OpaqueDef(..) = t.kind { + self.has_type_alias_impl_trait = true; + } else { + hir::intravisit::walk_ty(self, t); + } + } + } + let mut has_tait = HasTait { has_type_alias_impl_trait: false }; + has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0); + has_tait.has_type_alias_impl_trait +} 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 957a6bb348109..0544c5ca86619 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -1,7 +1,7 @@ use rustc_errors::StashKey; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem}; +use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::DUMMY_SP; @@ -74,9 +74,14 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local hidden.ty } else { + let mut parent_def_id = def_id; + while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy { + // Account for `type Alias = impl Trait;` (#116031) + parent_def_id = tcx.local_parent(parent_def_id); + } let reported = tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), - name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), + name: tcx.item_name(parent_def_id.to_def_id()), what: match tcx.hir().get(scope) { _ if scope == hir::CRATE_HIR_ID => "module", Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4705e40988b2f..0efe82b20eebf 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -963,6 +963,25 @@ pub struct InherentTyOutside { pub span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct DispatchFromDynCoercion<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_same_note)] + pub note: bool, + pub source_path: String, + pub target_path: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_repr, code = "E0378")] +pub struct DispatchFromDynRepr { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = "E0390")] #[help] @@ -1025,3 +1044,108 @@ pub struct InherentNominal { #[label] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_zst, code = "E0378")] +#[note] +pub struct DispatchFromDynZST<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct DispatchFromDynSingle<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_single_note)] + pub note: bool, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_multi, code = "E0378")] +#[note] +pub struct DispatchFromDynMulti { + #[primary_span] + pub span: Span, + #[note(hir_analysis_coercions_note)] + pub coercions_note: bool, + pub number: usize, + pub coercions: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0376")] +pub struct DispatchFromDynStruct<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0377")] +pub struct DispatchFromDynSame<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_same_note)] + pub note: bool, + pub source_path: String, + pub target_path: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0374")] +pub struct CoerceUnsizedOneField<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_single_note)] + pub note: bool, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_multi, code = "E0375")] +#[note] +pub struct CoerceUnsizedMulti { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_coercions_note)] + pub coercions_note: bool, + pub number: usize, + pub coercions: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct CoerceUnsizedMay<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_trait_cannot_impl_for_ty, code = "E0204")] +pub struct TraitCannotImplForTy { + #[primary_span] + pub span: Span, + pub trait_name: String, + #[label] + pub label_spans: Vec, + #[subdiagnostic] + pub notes: Vec, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_requires_note)] +pub struct ImplForTyRequires { + #[primary_span] + pub span: MultiSpan, + pub error_predicate: String, + pub trait_name: String, + pub ty: String, +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 3760195a5e8ec..b4af321fcc9d2 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -196,7 +196,7 @@ fn get_impl_args( let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors); + let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors); return Err(guar); } @@ -376,9 +376,9 @@ fn check_predicates<'tcx>( let always_applicable_traits = impl1_predicates .iter() .copied() - .filter(|(clause, _span)| { + .filter(|&(clause, _span)| { matches!( - trait_predicate_kind(tcx, clause.as_predicate()), + trait_specialization_kind(tcx, clause), Some(TraitSpecializationKind::AlwaysApplicable) ) }) @@ -402,7 +402,7 @@ fn check_predicates<'tcx>( .iter() .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) { - check_specialization_on(tcx, clause.as_predicate(), span) + check_specialization_on(tcx, clause, span) } } } @@ -441,19 +441,16 @@ fn trait_predicates_eq<'tcx>( } #[instrument(level = "debug", skip(tcx))] -fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) { - match predicate.kind().skip_binder() { +fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) { + match clause.kind().skip_binder() { // Global predicates are either always true or always false, so we // are fine to specialize on. - _ if predicate.is_global() => (), + _ if clause.is_global() => (), // We allow specializing on explicitly marked traits with no associated // items. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { - trait_ref, - polarity: _, - })) => { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { if !matches!( - trait_predicate_kind(tcx, predicate), + trait_specialization_kind(tcx, clause), Some(TraitSpecializationKind::Marker) ) { tcx.sess @@ -467,10 +464,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc .emit(); } } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty, - term, - })) => { + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { tcx.sess .struct_span_err( span, @@ -478,7 +472,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc ) .emit(); } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => { + ty::ClauseKind::ConstArgHasType(..) => { // FIXME(min_specialization), FIXME(const_generics): // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure // about the actual rules that would be sound. Can't just always error here because otherwise @@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc } _ => { tcx.sess - .struct_span_err(span, format!("cannot specialize on predicate `{predicate}`")) + .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) .emit(); } } } -fn trait_predicate_kind<'tcx>( +fn trait_specialization_kind<'tcx>( tcx: TyCtxt<'tcx>, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, ) -> Option { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { - trait_ref, - polarity: _, - })) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous => None, + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { + Some(tcx.trait_def(trait_ref.def_id).specialization_kind) + } + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(..) => None, } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index ef788935efbae..03963925d3dbd 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -99,7 +99,6 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; -use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::middle; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -107,8 +106,7 @@ use rustc_middle::util; use rustc_session::parse::feature_err; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; -use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits; use astconv::{AstConv, OnlySelfBounds}; use bounds::Bounds; @@ -151,28 +149,6 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions }); } -fn require_same_types<'tcx>( - tcx: TyCtxt<'tcx>, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - expected: Ty<'tcx>, - actual: Ty<'tcx>, -) { - let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); - match ocx.eq(cause, param_env, expected, actual) { - Ok(()) => { - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); - } - } - Err(err) => { - infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); - } - } -} - pub fn provide(providers: &mut Providers) { collect::provide(providers); coherence::provide(providers); diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 8a40509d7cc5f..61d9c989e2fd9 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -6,7 +6,7 @@ use hir::def_id::{DefId, LocalDefId}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use super::terms::VarianceTerm::*; @@ -78,9 +78,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id), - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { constraint_cx.build_constraints_for_item(def_id) } _ => {} @@ -110,8 +108,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // The type as returned by `type_of` is the underlying type and generally not a weak projection. // Therefore we need to check the `DefKind` first. - if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id) - && (lazy || ty.has_opaque_types()) + if let DefKind::TyAlias = tcx.def_kind(def_id) + && tcx.type_alias_is_lazy(def_id) { self.add_constraints_from_ty(current_item, ty, self.covariant); return; @@ -314,11 +312,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } - ty::Placeholder(..) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Bound(..) - | ty::Infer(..) => { + ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Bound(..) | ty::Infer(..) => { bug!("unexpected type encountered in variance inference: {}", ty); } } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index d69d7ff904acc..9fb39a0e93b6c 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -8,7 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; -use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can @@ -56,9 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { // These are inferred. let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); @@ -194,5 +192,5 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc } } } - tcx.arena.alloc_from_iter(collector.variances.into_iter()) + tcx.arena.alloc_from_iter(collector.variances) } diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 1a8ec5f085333..275df24956ccc 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -12,7 +12,7 @@ use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, TyCtxt}; use std::fmt; use self::VarianceTerm::*; @@ -97,9 +97,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id), - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { terms_cx.add_inferreds_for_item(def_id) } _ => {} diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 89efdc269c466..8587b009f25aa 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2304,7 +2304,7 @@ impl<'a> State<'a> { match header.asyncness { hir::IsAsync::NotAsync => {} - hir::IsAsync::Async => self.word_nbsp("async"), + hir::IsAsync::Async(_) => self.word_nbsp("async"), } self.print_unsafety(header.unsafety); diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 921a5f5154a14..9950a226333e8 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -83,16 +83,6 @@ hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*cons hir_typeck_invalid_callee = expected function, found {$ty} -hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` -hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item -hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count} - -hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect - .suggestion = change the type from `{$found_ty}` to `{$expected_ty}` - -hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect - .suggestion = change the type from `{$found_ty}` to `{$expected_ty}` - hir_typeck_lossy_provenance_int2ptr = strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}` .suggestion = use `.with_addr()` to adjust a valid pointer in the same allocation, to this address diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 3319b52e24641..81fe0cc489e33 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -2,6 +2,7 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; use rustc_errors::Diagnostic; use rustc_hir::{self as hir, ExprKind}; +use rustc_hir_pretty::ty_to_string; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, Ty}; @@ -252,7 +253,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) - let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span); + let hir_id = self.tcx.hir().parent_id(self.tcx.hir().parent_id(then_expr.hir_id)); + let ret_reason = self.maybe_get_coercion_reason(hir_id, span); let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); let mut error = false; coercion.coerce_forced_unit( @@ -275,11 +277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error } - fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> { - let node = { - let rslt = self.tcx.hir().parent_id(self.tcx.hir().parent_id(hir_id)); - self.tcx.hir().get(rslt) - }; + pub fn maybe_get_coercion_reason( + &self, + hir_id: hir::HirId, + sp: Span, + ) -> Option<(Span, String)> { + let node = self.tcx.hir().get(hir_id); if let hir::Node::Block(block) = node { // check that the body's parent is an fn let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id)); @@ -289,9 +292,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // check that the `if` expr without `else` is the fn body's expr if expr.span == sp { return self.get_fn_decl(hir_id).and_then(|(_, fn_decl, _)| { - let span = fn_decl.output.span(); - let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?; - Some((span, format!("expected `{snippet}` because of this return type"))) + let (ty, span) = match fn_decl.output { + hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span), + hir::FnRetTy::Return(ty) => (ty_to_string(ty), ty.span), + }; + Some((span, format!("expected `{ty}` because of this return type"))) }); } } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index b39919ece7145..f2c58ee27029b 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -788,7 +788,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let effect = match const_context { _ if host_always_on => tcx.consts.true_, - Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_, + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => { + tcx.consts.false_ + } Some(hir::ConstContext::ConstFn) => { let args = ty::GenericArgs::identity_for_item(tcx, context); args.host_effect_param().expect("ConstContext::Maybe must have host effect param") diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index fa779701e61ed..2b1ac7f353777 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -129,7 +129,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::RawPtr(_) | ty::Ref(..) | ty::FnDef(..) @@ -725,6 +724,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { }, // array-ptr-cast Ptr(mt) => { + if !fcx.type_is_sized_modulo_regions(fcx.param_env, mt.ty) { + return Err(CastError::IllegalCast); + } self.check_ref_cast(fcx, TypeAndMut { mutbl, ty: inner_ty }, mt) } _ => Err(CastError::NonScalar), @@ -735,7 +737,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { } _ => return Err(CastError::NonScalar), }; - if let ty::Adt(adt_def, _) = *self.expr_ty.kind() { if adt_def.did().krate != LOCAL_CRATE { if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { @@ -743,7 +744,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } } - match (t_from, t_cast) { // These types have invariants! can't cast into them. (_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar), diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 1fc1e5aca2b3c..c8ffd7d15067d 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,7 +1,6 @@ +use std::cell::RefCell; + use crate::coercion::CoerceMany; -use crate::errors::{ - LangStartIncorrectNumberArgs, LangStartIncorrectParam, LangStartIncorrectRetTy, -}; use crate::gather_locals::GatherLocalsVisitor; use crate::FnCtxt; use crate::GeneratorTypes; @@ -9,14 +8,15 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir_analysis::check::fn_maybe_err; +use rustc_hir_analysis::check::{check_function_signature, fn_maybe_err}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; +use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; -use std::cell::RefCell; +use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; /// Helper used for fns and closures. Does the grungy work of checking a function /// body and returns the function context used for that purpose, since in the case of a fn item @@ -113,7 +113,11 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + let return_or_body_span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => body.value.span, + hir::FnRetTy::Return(ty) => ty.span, + }; + fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType); fcx.check_return_expr(&body.value, false); // We insert the deferred_generator_interiors entry after visiting the body. @@ -166,52 +170,17 @@ pub(super) fn check_fn<'a, 'tcx>( if let Some(panic_impl_did) = tcx.lang_items().panic_impl() && panic_impl_did == fn_def_id.to_def_id() { - check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); + check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig); } if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == fn_def_id.to_def_id() { - check_lang_start_fn(tcx, fn_sig, decl, fn_def_id); + check_lang_start_fn(tcx, fn_sig, fn_def_id); } gen_ty } -fn check_panic_info_fn( - tcx: TyCtxt<'_>, - fn_id: LocalDefId, - fn_sig: ty::FnSig<'_>, - decl: &hir::FnDecl<'_>, - declared_ret_ty: Ty<'_>, -) { - let Some(panic_info_did) = tcx.lang_items().panic_info() else { - tcx.sess.err("language item required, but not found: `panic_info`"); - return; - }; - - if *declared_ret_ty.kind() != ty::Never { - tcx.sess.span_err(decl.output.span(), "return type should be `!`"); - } - - let inputs = fn_sig.inputs(); - if inputs.len() != 1 { - tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); - return; - } - - let arg_is_panic_info = match *inputs[0].kind() { - ty::Ref(region, ty, mutbl) => match *ty.kind() { - ty::Adt(ref adt, _) => { - adt.did() == panic_info_did && mutbl.is_not() && !region.is_static() - } - _ => false, - }, - _ => false, - }; - - if !arg_is_panic_info { - tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); - } - +fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) { let DefKind::Fn = tcx.def_kind(fn_id) else { let span = tcx.def_span(fn_id); tcx.sess.span_err(span, "should be a function"); @@ -227,125 +196,87 @@ fn check_panic_info_fn( let span = tcx.def_span(fn_id); tcx.sess.span_err(span, "should have no const parameters"); } -} - -fn check_lang_start_fn<'tcx>( - tcx: TyCtxt<'tcx>, - fn_sig: ty::FnSig<'tcx>, - decl: &'tcx hir::FnDecl<'tcx>, - def_id: LocalDefId, -) { - let inputs = fn_sig.inputs(); - - let arg_count = inputs.len(); - if arg_count != 4 { - tcx.sess.emit_err(LangStartIncorrectNumberArgs { - params_span: tcx.def_span(def_id), - found_param_count: arg_count, - }); - } - - // only check args if they should exist by checking the count - // note: this does not handle args being shifted or their order swapped very nicely - // but it's a lang item, users shouldn't frequently encounter this - - // first arg is `main: fn() -> T` - if let Some(&main_arg) = inputs.get(0) { - // make a Ty for the generic on the fn for diagnostics - // FIXME: make the lang item generic checks check for the right generic *kind* - // 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 = 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 = 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 = || { - tcx.sess.emit_err(LangStartIncorrectParam { - param_span: decl.inputs[0].span, - param_num: 1, - expected_ty: expected_ty, - found_ty: main_arg, - }); - }; - - if let ty::FnPtr(main_fn_sig) = main_arg.kind() { - let main_fn_inputs = main_fn_sig.inputs(); - if main_fn_inputs.iter().count() != 0 { - emit_main_fn_arg_err(); - } - - let output = main_fn_sig.output(); - output.map_bound(|ret_ty| { - // if the output ty is a generic, it's probably the right one - if !matches!(ret_ty.kind(), ty::Param(_)) { - emit_main_fn_arg_err(); - } - }); - } else { - emit_main_fn_arg_err(); - } - } - - // second arg is isize - if let Some(&argc_arg) = inputs.get(1) { - if argc_arg != tcx.types.isize { - tcx.sess.emit_err(LangStartIncorrectParam { - param_span: decl.inputs[1].span, - param_num: 2, - expected_ty: tcx.types.isize, - found_ty: argc_arg, - }); - } - } - - // third arg is `*const *const u8` - if let Some(&argv_arg) = inputs.get(2) { - let mut argv_is_okay = false; - if let ty::RawPtr(outer_ptr) = argv_arg.kind() { - if outer_ptr.mutbl.is_not() { - if let ty::RawPtr(inner_ptr) = outer_ptr.ty.kind() { - if inner_ptr.mutbl.is_not() && inner_ptr.ty == tcx.types.u8 { - argv_is_okay = true; - } - } - } - } - if !argv_is_okay { - let inner_ptr_ty = - Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 }); - let expected_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, - expected_ty, - found_ty: argv_arg, - }); - } - } + let Some(panic_info_did) = tcx.lang_items().panic_info() else { + tcx.sess.err("language item required, but not found: `panic_info`"); + return; + }; - // fourth arg is `sigpipe: u8` - if let Some(&sigpipe_arg) = inputs.get(3) { - if sigpipe_arg != tcx.types.u8 { - tcx.sess.emit_err(LangStartIncorrectParam { - param_span: decl.inputs[3].span, - param_num: 4, - expected_ty: tcx.types.u8, - found_ty: sigpipe_arg, - }); - } - } + // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` + let panic_info_ty = tcx.type_of(panic_info_did).instantiate( + tcx, + &[ty::GenericArg::from(ty::Region::new_late_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }, + ))], + ); + let panic_info_ref_ty = Ty::new_imm_ref( + tcx, + ty::Region::new_late_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, + ), + panic_info_ty, + ); + + let bounds = tcx.mk_bound_variable_kinds(&[ + ty::BoundVariableKind::Region(ty::BrAnon), + ty::BoundVariableKind::Region(ty::BrAnon), + ]); + let expected_sig = ty::Binder::bind_with_vars( + tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.unsafety, Abi::Rust), + bounds, + ); + + check_function_signature( + tcx, + ObligationCause::new( + tcx.def_span(fn_id), + fn_id, + ObligationCauseCode::LangFunctionType(sym::panic_impl), + ), + fn_id.into(), + expected_sig, + ); +} - // output type is isize - if fn_sig.output() != tcx.types.isize { - tcx.sess.emit_err(LangStartIncorrectRetTy { - ret_span: decl.output.span(), - expected_ty: tcx.types.isize, - found_ty: fn_sig.output(), - }); - } +fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: LocalDefId) { + // build type `fn(main: fn() -> T, argc: isize, argv: *const *const u8, sigpipe: u8)` + + // make a Ty for the generic on the fn for diagnostics + // FIXME: make the lang item generic checks check for the right generic *kind* + // 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 = Ty::new_param(tcx, fn_generic.index, fn_generic.name); + let main_fn_ty = Ty::new_fn_ptr( + tcx, + Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust)), + ); + + let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( + [ + main_fn_ty, + tcx.types.isize, + Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8)), + tcx.types.u8, + ], + tcx.types.isize, + false, + fn_sig.unsafety, + Abi::Rust, + )); + + check_function_signature( + tcx, + ObligationCause::new( + tcx.def_span(def_id), + def_id, + ObligationCauseCode::LangFunctionType(sym::start), + ), + def_id.into(), + expected_sig, + ); } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2c16f21b49160..5c3f2b85966a8 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable}; +use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -83,6 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.annotate_expected_due_to_let_ty(err, expr, error); + self.annotate_loop_expected_due_to_inference(err, expr, error); // FIXME(#73154): For now, we do leak check when coercing function // pointers in typeck, instead of only during borrowck. This can lead @@ -503,12 +504,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // incompatible fix at the original mismatch site. if matches!(source, TypeMismatchSource::Ty(_)) && let Some(ideal_method) = ideal_method + && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) + // HACK(compiler-errors): We don't actually consider the implications + // of our inference guesses in `emit_type_mismatch_suggestions`, so + // only suggest things when we know our type error is precisely due to + // a type mismatch, and not via some projection or something. See #116155. + && !ideal_arg_ty.has_non_region_infer() { self.emit_type_mismatch_suggestions( err, arg_expr, arg_ty, - self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]), + ideal_arg_ty, None, None, ); @@ -527,6 +534,136 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + // When encountering a type error on the value of a `break`, try to point at the reason for the + // expected type. + pub fn annotate_loop_expected_due_to_inference( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + error: Option>, + ) { + let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else { + return; + }; + let mut parent_id = self.tcx.hir().parent_id(expr.hir_id); + let mut parent; + 'outer: loop { + // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement. + let Some( + hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) + | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) + | hir::Node::Expr(&ref p), + ) = self.tcx.hir().find(parent_id) + else { + break; + }; + parent = p; + parent_id = self.tcx.hir().parent_id(parent_id); + let hir::ExprKind::Break(destination, _) = parent.kind else { + continue; + }; + let mut parent_id = parent_id; + let mut direct = false; + loop { + // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to. + let parent = match self.tcx.hir().find(parent_id) { + Some(hir::Node::Expr(&ref parent)) => { + parent_id = self.tcx.hir().parent_id(parent.hir_id); + parent + } + Some(hir::Node::Stmt(hir::Stmt { + hir_id, + kind: hir::StmtKind::Semi(&ref parent) | hir::StmtKind::Expr(&ref parent), + .. + })) => { + parent_id = self.tcx.hir().parent_id(*hir_id); + parent + } + Some(hir::Node::Block(_)) => { + parent_id = self.tcx.hir().parent_id(parent_id); + parent + } + _ => break, + }; + if let hir::ExprKind::Loop(..) = parent.kind { + // When you have `'a: loop { break; }`, the `break` corresponds to the labeled + // loop, so we need to account for that. + direct = !direct; + } + if let hir::ExprKind::Loop(block, label, _, span) = parent.kind + && (destination.label == label || direct) + { + if let Some((reason_span, message)) = + self.maybe_get_coercion_reason(parent_id, parent.span) + { + err.span_label(reason_span, message); + err.span_label( + span, + format!("this loop is expected to be of type `{expected}`"), + ); + break 'outer; + } else { + // Locate all other `break` statements within the same `loop` that might + // have affected inference. + struct FindBreaks<'tcx> { + label: Option, + uses: Vec<&'tcx hir::Expr<'tcx>>, + nest_depth: usize, + } + impl<'tcx> Visitor<'tcx> for FindBreaks<'tcx> { + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { + let nest_depth = self.nest_depth; + if let hir::ExprKind::Loop(_, label, _, _) = ex.kind { + if label == self.label { + // Account for `'a: loop { 'a: loop {...} }`. + return; + } + self.nest_depth += 1; + } + if let hir::ExprKind::Break(destination, _) = ex.kind + && (self.label == destination.label + // Account for `loop { 'a: loop { loop { break; } } }`. + || destination.label.is_none() && self.nest_depth == 0) + { + self.uses.push(ex); + } + hir::intravisit::walk_expr(self, ex); + self.nest_depth = nest_depth; + } + } + let mut expr_finder = FindBreaks { label, uses: vec![], nest_depth: 0 }; + expr_finder.visit_block(block); + let mut exit = false; + for ex in expr_finder.uses { + let hir::ExprKind::Break(_, val) = ex.kind else { + continue; + }; + let ty = match val { + Some(val) => { + match self.typeck_results.borrow().expr_ty_adjusted_opt(val) { + None => continue, + Some(ty) => ty, + } + } + None => self.tcx.types.unit, + }; + if self.can_eq(self.param_env, ty, expected) { + err.span_label( + ex.span, + "expected because of this `break`", + ); + exit = true; + } + } + if exit { + break 'outer; + } + } + } + } + } + } + fn annotate_expected_due_to_let_ty( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 7152585d44087..8efccd5ba3eef 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -110,7 +110,7 @@ pub struct AddressOfTemporaryTaken { pub enum AddReturnTypeSuggestion { #[suggestion( hir_typeck_add_return_type_add, - code = "-> {found} ", + code = " -> {found}", applicability = "machine-applicable" )] Add { @@ -120,7 +120,7 @@ pub enum AddReturnTypeSuggestion { }, #[suggestion( hir_typeck_add_return_type_missing_here, - code = "-> _ ", + code = " -> _", applicability = "has-placeholders" )] MissingHere { @@ -236,39 +236,6 @@ impl AddToDiagnostic for TypeMismatchFruTypo { } } -#[derive(Diagnostic)] -#[diag(hir_typeck_lang_start_incorrect_number_params)] -#[note(hir_typeck_lang_start_incorrect_number_params_note_expected_count)] -#[note(hir_typeck_lang_start_expected_sig_note)] -pub struct LangStartIncorrectNumberArgs { - #[primary_span] - pub params_span: Span, - pub found_param_count: usize, -} - -#[derive(Diagnostic)] -#[diag(hir_typeck_lang_start_incorrect_param)] -pub struct LangStartIncorrectParam<'tcx> { - #[primary_span] - #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")] - pub param_span: Span, - - pub param_num: usize, - pub expected_ty: Ty<'tcx>, - pub found_ty: Ty<'tcx>, -} - -#[derive(Diagnostic)] -#[diag(hir_typeck_lang_start_incorrect_ret_ty)] -pub struct LangStartIncorrectRetTy<'tcx> { - #[primary_span] - #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")] - pub ret_span: Span, - - pub expected_ty: Ty<'tcx>, - pub found_ty: Ty<'tcx>, -} - #[derive(LintDiagnostic)] #[diag(hir_typeck_lossy_provenance_int2ptr)] #[help] diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 70d1dad8a6f46..a00f3c5d0d8c3 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -41,9 +41,11 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::InferOk; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; -use rustc_middle::middle::stability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; -use rustc_middle::ty::error::TypeError::FieldMisMatch; +use rustc_middle::ty::error::{ + ExpectedFound, + TypeError::{FieldMisMatch, Sorts}, +}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt}; use rustc_session::errors::ExprParenthesesNeeded; @@ -525,8 +527,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, }; - if let ty::FnDef(did, ..) = *ty.kind() { + if let ty::FnDef(did, callee_args) = *ty.kind() { let fn_sig = ty.fn_sig(tcx); + + // HACK: whenever we get a FnDef in a non-const context, enforce effects to get the + // default `host = true` to avoid inference errors later. + if tcx.hir().body_const_context(self.body_id).is_none() { + self.enforce_context_effects(expr.hir_id, qpath.span(), did, callee_args); + } if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute { @@ -658,15 +666,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_mismatched_types_on_tail( &mut err, expr, ty, e_ty, target_id, ); + let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty })); + self.annotate_loop_expected_due_to_inference(&mut err, expr, error); if let Some(val) = ty_kind_suggestion(ty) { - let label = destination - .label - .map(|l| format!(" {}", l.ident)) - .unwrap_or_else(String::new); - err.span_suggestion( - expr.span, + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), "give it a value of the expected type", - format!("break{label} {val}"), + format!(" {val}"), Applicability::HasPlaceholders, ); } @@ -711,7 +717,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ... except when we try to 'break rust;'. // ICE this expression in particular (see #43162). if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind { - if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust { + if let [segment] = path.segments && segment.ident.name == sym::rust { fatally_break_rust(self.tcx); } } @@ -1578,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_struct_fields( adt_ty, expected, - expr.hir_id, + expr, qpath.span(), variant, fields, base_expr, - expr.span, ); self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); @@ -1594,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, adt_ty: Ty<'tcx>, expected: Expectation<'tcx>, - expr_id: hir::HirId, + expr: &hir::Expr<'_>, span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, - expr_span: Span, ) { let tcx = self.tcx; @@ -1639,7 +1643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // struct-like enums (yet...), but it's definitely not // a bug to have constructed one. if adt_kind != AdtKind::Enum { - tcx.check_stability(v_field.did, Some(expr_id), field.span, None); + tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None); } self.field_ty(field.span, v_field, args) @@ -1655,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.report_unknown_field( adt_ty, variant, + expr, field, ast_fields, adt.variant_descr(), - expr_span, ) }; @@ -1724,7 +1728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .map(|f| { let fru_ty = self - .normalize(expr_span, self.field_ty(base_expr.span, f, fresh_args)); + .normalize(expr.span, self.field_ty(base_expr.span, f, fresh_args)); let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id); if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, args); @@ -1807,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, args) if adt.is_struct() => variant .fields .iter() - .map(|f| self.normalize(expr_span, f.ty(self.tcx, args))) + .map(|f| self.normalize(expr.span, f.ty(self.tcx, args))) .collect(), _ => { self.tcx @@ -1817,13 +1821,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }; - self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); + self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys); } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() { debug!(?remaining_fields); let private_fields: Vec<&ty::FieldDef> = variant .fields .iter() - .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr_id), tcx)) + .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx)) .collect(); if !private_fields.is_empty() { @@ -2042,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, + expr: &hir::Expr<'_>, field: &hir::ExprField<'_>, skip_fields: &[hir::ExprField<'_>], kind_name: &str, - expr_span: Span, ) -> ErrorGuaranteed { if variant.is_recovered() { let guar = self .tcx .sess - .delay_span_bug(expr_span, "parser recovered but no error was emitted"); + .delay_span_bug(expr.span, "parser recovered but no error was emitted"); self.set_tainted_by_errors(guar); return guar; } @@ -2095,7 +2099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion_verbose( - expr_span, + expr.span, format!( "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, @@ -2113,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(variant_ident_span, format!("`{ty}` defined here")); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion_verbose( - expr_span, + expr.span, format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",), format!("{ty}(/* fields */)"), Applicability::HasPlaceholders, @@ -2122,9 +2126,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, _ => { // prevent all specified fields from being suggested - let skip_fields: Vec<_> = skip_fields.iter().map(|x| x.ident.name).collect(); + let available_field_names = self.available_field_names(variant, expr, skip_fields); if let Some(field_name) = - self.suggest_field_name(variant, field.ident.name, &skip_fields, expr_span) + find_best_match_for_name(&available_field_names, field.ident.name, None) { err.span_suggestion( field.ident.span, @@ -2146,10 +2150,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("`{ty}` does not have this field"), ); } - let mut available_field_names = - self.available_field_names(variant, expr_span); - available_field_names - .retain(|name| skip_fields.iter().all(|skip| name != skip)); if available_field_names.is_empty() { err.note("all struct fields are already assigned"); } else { @@ -2167,63 +2167,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() } - // Return a hint about the closest match in field names - fn suggest_field_name( - &self, - variant: &'tcx ty::VariantDef, - field: Symbol, - skip: &[Symbol], - // The span where stability will be checked - span: Span, - ) -> Option { - let names = variant - .fields - .iter() - .filter_map(|field| { - // ignore already set fields and private fields from non-local crates - // and unstable fields. - if skip.iter().any(|&x| x == field.name) - || (!variant.def_id.is_local() && !field.vis.is_public()) - || matches!( - self.tcx.eval_stability(field.did, None, span, None), - stability::EvalResult::Deny { .. } - ) - { - None - } else { - Some(field.name) - } - }) - .collect::>(); - - find_best_match_for_name(&names, field, None) - } - fn available_field_names( &self, variant: &'tcx ty::VariantDef, - access_span: Span, + expr: &hir::Expr<'_>, + skip_fields: &[hir::ExprField<'_>], ) -> Vec { - let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); variant .fields .iter() .filter(|field| { - let def_scope = self - .tcx - .adjust_ident_and_get_scope( - field.ident(self.tcx), - variant.def_id, - body_owner_hir_id, - ) - .1; - field.vis.is_accessible_from(def_scope, self.tcx) - && !matches!( - self.tcx.eval_stability(field.did, None, access_span, None), - stability::EvalResult::Deny { .. } - ) + skip_fields.iter().all(|&skip| skip.ident.name != field.name) + && self.is_field_suggestable(field, expr.hir_id, expr.span) }) - .filter(|field| !self.tcx.is_doc_hidden(field.did)) .map(|field| field.name) .collect() } @@ -2453,7 +2409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_first_deref_field(&mut err, expr, base, ident); } ty::Adt(def, _) if !def.is_enum() => { - self.suggest_fields_on_recordish(&mut err, def, ident, expr.span); + self.suggest_fields_on_recordish(&mut err, expr, def, ident); } ty::Param(param_ty) => { self.point_at_param_definition(&mut err, param_ty); @@ -2615,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_fields_on_recordish( &self, err: &mut Diagnostic, + expr: &hir::Expr<'_>, def: ty::AdtDef<'tcx>, field: Ident, - access_span: Span, ) { + let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]); if let Some(suggested_field_name) = - self.suggest_field_name(def.non_enum_variant(), field.name, &[], access_span) + find_best_match_for_name(&available_field_names, field.name, None) { err.span_suggestion( field.span, @@ -2630,12 +2587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { err.span_label(field.span, "unknown field"); - let struct_variant_def = def.non_enum_variant(); - let field_names = self.available_field_names(struct_variant_def, access_span); - if !field_names.is_empty() { + if !available_field_names.is_empty() { err.note(format!( "available fields are: {}", - self.name_series_display(field_names), + self.name_series_display(available_field_names), )); } } @@ -3003,7 +2958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There should be at least one error reported. If not, we // will still delay a span bug in `report_fulfillment_errors`. Ok::<_, NoSolution>(( - self.err_ctxt().report_fulfillment_errors(&errors), + self.err_ctxt().report_fulfillment_errors(errors), impl_trait_ref.args.type_at(1), element_ty, )) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 840910732d89f..8bc66ac5509be 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -664,10 +664,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ); self.walk_pat(discr_place, arm.pat, arm.guard.is_some()); - if let Some(hir::Guard::If(e)) = arm.guard { - self.consume_expr(e) - } else if let Some(hir::Guard::IfLet(ref l)) = arm.guard { - self.consume_expr(l.init) + match arm.guard { + Some(hir::Guard::If(ref e)) => self.consume_expr(e), + Some(hir::Guard::IfLet(ref l)) => { + self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow)) + } + None => {} } self.consume_expr(arm.body); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c94cfde06707a..5dae74a1f9b37 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -509,21 +509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { typeck_results.rvalue_scopes = rvalue_scopes; } - pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) { - if self.tcx.sess.opts.unstable_opts.drop_tracking_mir { - self.save_generator_interior_predicates(def_id); - return; - } - - self.select_obligations_where_possible(|_| {}); - - let mut generators = self.deferred_generator_interiors.borrow_mut(); - for (_, body_id, interior, kind) in generators.drain(..) { - crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind); - self.select_obligations_where_possible(|_| {}); - } - } - /// Unify the inference variables corresponding to generator witnesses, and save all the /// predicates that were stalled on those inference variables. /// @@ -533,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// We must not attempt to select obligations after this method has run, or risk query cycle /// ICE. #[instrument(level = "debug", skip(self))] - fn save_generator_interior_predicates(&self, def_id: DefId) { + pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) { // Try selecting all obligations that are not blocked on inference variables. // Once we start unifying generator witnesses, trying to select obligations on them will // trigger query cycle ICEs, as doing so requires MIR. @@ -550,7 +535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); - let witness = Ty::new_generator_witness_mir(self.tcx, expr_def_id.to_def_id(), args); + let witness = Ty::new_generator_witness(self.tcx, expr_def_id.to_def_id(), args); // Unify `interior` with `witness` and collect all the resulting obligations. let span = self.tcx.hir().body(body_id).value.span; @@ -579,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !errors.is_empty() { self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); - self.err_ctxt().report_fulfillment_errors(&errors); + self.err_ctxt().report_fulfillment_errors(errors); } } @@ -592,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.adjust_fulfillment_errors_for_expr_obligation(&mut result); - self.err_ctxt().report_fulfillment_errors(&result); + self.err_ctxt().report_fulfillment_errors(result); } } @@ -1492,7 +1477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { Ok(normalized_ty) => normalized_ty, Err(errors) => { - let guar = self.err_ctxt().report_fulfillment_errors(&errors); + let guar = self.err_ctxt().report_fulfillment_errors(errors); return Ty::new_error(self.tcx,guar); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 4def78673841c..c0332a48be3df 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -273,11 +273,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // This check is here because there is currently no way to express a trait bound for `FnDef` types only. if is_const_eval_select && (1..=2).contains(&idx) { - if let ty::FnDef(def_id, _) = checked_ty.kind() { - if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) { - self.tcx - .sess - .emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span }); + if let ty::FnDef(def_id, args) = *checked_ty.kind() { + if idx == 1 { + if !self.tcx.is_const_fn_raw(def_id) { + self.tcx.sess.emit_err(errors::ConstSelectMustBeConst { + span: provided_arg.span, + }); + } else { + self.enforce_context_effects( + provided_arg.hir_id, + provided_arg.span, + def_id, + args, + ) + } } } else { self.tcx.sess.emit_err(errors::ConstSelectMustBeFn { @@ -1361,10 +1370,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => bug!("unexpected type: {:?}", ty.normalized), }, - Res::Def( - DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy, - _, - ) + Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() { Some(adt) if !adt.is_enum() => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index d2a53ee8b5e10..9999fa2e59ccf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -65,6 +65,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); self.suggest_missing_semicolon(err, expr, expected, false); let mut pointing_at_return_type = false; + if let hir::ExprKind::Break(..) = expr.kind { + // `break` type mismatches provide better context for tail `loop` expressions. + return false; + } if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type( err, @@ -778,8 +782,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } hir::FnRetTy::Return(hir_ty) => { - let span = hir_ty.span; - if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind && let hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(op_ty), @@ -795,28 +797,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?found); if found.is_suggestable(self.tcx, false) { if term.span.is_empty() { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }); + err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span: term.span, found: found.to_string() }); return true; } else { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: term.span, expected }); } } - } - - // Only point to return type if the expected type is the return type, as if they - // are not, the expectation must have been caused by something else. - debug!("return type {:?}", hir_ty); - let ty = self.astconv().ast_ty_to_ty(hir_ty); - debug!("return type {:?}", ty); - debug!("expected type {:?}", expected); - let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); - let ty = Binder::bind_with_vars(ty, bound_vars); - let ty = self.normalize(span, ty); - let ty = self.tcx.erase_late_bound_regions(ty); - if self.can_coerce(expected, ty) { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); - self.try_suggest_return_impl_trait(err, expected, ty, fn_id); - return true; + } else { + // Only point to return type if the expected type is the return type, as if they + // are not, the expectation must have been caused by something else. + debug!("return type {:?}", hir_ty); + let ty = self.astconv().ast_ty_to_ty(hir_ty); + debug!("return type {:?}", ty); + debug!("expected type {:?}", expected); + let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); + let ty = Binder::bind_with_vars(ty, bound_vars); + let ty = self.normalize(hir_ty.span, ty); + let ty = self.tcx.erase_late_bound_regions(ty); + if self.can_coerce(expected, ty) { + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected }); + self.try_suggest_return_impl_trait(err, expected, ty, fn_id); + return true; + } } } _ => {} @@ -987,10 +989,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let bound_vars = self.tcx.late_bound_vars(fn_id); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = match self.tcx.asyncness(fn_id.owner) { - hir::IsAsync::Async => self.get_impl_future_output_ty(ty).unwrap_or_else(|| { + ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| { span_bug!(fn_decl.output.span(), "failed to get output type of async function") }), - hir::IsAsync::NotAsync => ty, + ty::Asyncness::No => ty, }; let ty = self.normalize(expr.span, ty); if self.can_coerce(found, ty) { @@ -1683,4 +1685,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } } + + pub(crate) fn is_field_suggestable( + &self, + field: &ty::FieldDef, + hir_id: HirId, + span: Span, + ) -> bool { + // The field must be visible in the containing module. + field.vis.is_accessible_from(self.tcx.parent_module(hir_id), self.tcx) + // The field must not be unstable. + && !matches!( + self.tcx.eval_stability(field.did, None, rustc_span::DUMMY_SP, None), + rustc_middle::middle::stability::EvalResult::Deny { .. } + ) + // If the field is from an external crate it must not be `doc(hidden)`. + && (field.did.is_local() || !self.tcx.is_doc_hidden(field.did)) + // If the field is hygienic it must come from the same syntax context. + && self.tcx.def_ident_span(field.did).unwrap().normalize_to_macros_2_0().eq_ctxt(span) + } } diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs deleted file mode 100644 index cfedcee995659..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs +++ /dev/null @@ -1,601 +0,0 @@ -use super::{ - for_each_consumable, record_consumed_borrow::ConsumedAndBorrowedPlaces, DropRangesBuilder, - NodeInfo, PostOrderId, TrackedValue, TrackedValueIndex, -}; -use hir::{ - intravisit::{self, Visitor}, - Body, Expr, ExprKind, Guard, HirId, LoopIdError, -}; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_hir as hir; -use rustc_index::IndexVec; -use rustc_infer::infer::InferCtxt; -use rustc_middle::{ - hir::map::Map, - ty::{ParamEnv, TyCtxt, TypeVisitableExt, TypeckResults}, -}; -use std::mem::swap; - -/// Traverses the body to find the control flow graph and locations for the -/// relevant places are dropped or reinitialized. -/// -/// The resulting structure still needs to be iterated to a fixed point, which -/// can be done with propagate_to_fixpoint in cfg_propagate. -pub(super) fn build_control_flow_graph<'tcx>( - infcx: &InferCtxt<'tcx>, - typeck_results: &TypeckResults<'tcx>, - param_env: ParamEnv<'tcx>, - consumed_borrowed_places: ConsumedAndBorrowedPlaces, - body: &'tcx Body<'tcx>, - num_exprs: usize, -) -> (DropRangesBuilder, UnordSet) { - let mut drop_range_visitor = DropRangeVisitor::new( - infcx, - typeck_results, - param_env, - consumed_borrowed_places, - num_exprs, - ); - intravisit::walk_body(&mut drop_range_visitor, body); - - drop_range_visitor.drop_ranges.process_deferred_edges(); - if let Some(filename) = &infcx.tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg { - super::cfg_visualize::write_graph_to_file( - &drop_range_visitor.drop_ranges, - filename, - infcx.tcx, - ); - } - - (drop_range_visitor.drop_ranges, drop_range_visitor.places.borrowed_temporaries) -} - -/// This struct is used to gather the information for `DropRanges` to determine the regions of the -/// HIR tree for which a value is dropped. -/// -/// We are interested in points where a variables is dropped or initialized, and the control flow -/// of the code. We identify locations in code by their post-order traversal index, so it is -/// important for this traversal to match that in `RegionResolutionVisitor` and `InteriorVisitor`. -/// -/// We make several simplifying assumptions, with the goal of being more conservative than -/// necessary rather than less conservative (since being less conservative is unsound, but more -/// conservative is still safe). These assumptions are: -/// -/// 1. Moving a variable `a` counts as a move of the whole variable. -/// 2. Moving a partial path like `a.b.c` is ignored. -/// 3. Reinitializing through a field (e.g. `a.b.c = 5`) counts as a reinitialization of all of -/// `a`. -/// -/// Some examples: -/// -/// Rule 1: -/// ```rust -/// let mut a = (vec![0], vec![0]); -/// drop(a); -/// // `a` is not considered initialized. -/// ``` -/// -/// Rule 2: -/// ```rust -/// let mut a = (vec![0], vec![0]); -/// drop(a.0); -/// drop(a.1); -/// // `a` is still considered initialized. -/// ``` -/// -/// Rule 3: -/// ```compile_fail,E0382 -/// let mut a = (vec![0], vec![0]); -/// drop(a); -/// a.1 = vec![1]; -/// // all of `a` is considered initialized -/// ``` - -struct DropRangeVisitor<'a, 'tcx> { - typeck_results: &'a TypeckResults<'tcx>, - infcx: &'a InferCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - places: ConsumedAndBorrowedPlaces, - drop_ranges: DropRangesBuilder, - expr_index: PostOrderId, - label_stack: Vec<(Option, PostOrderId)>, -} - -impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { - fn new( - infcx: &'a InferCtxt<'tcx>, - typeck_results: &'a TypeckResults<'tcx>, - param_env: ParamEnv<'tcx>, - places: ConsumedAndBorrowedPlaces, - num_exprs: usize, - ) -> Self { - debug!("consumed_places: {:?}", places.consumed); - let drop_ranges = DropRangesBuilder::new( - places.consumed.iter().flat_map(|(_, places)| places.iter().cloned()), - infcx.tcx.hir(), - num_exprs, - ); - Self { - infcx, - typeck_results, - param_env, - places, - drop_ranges, - expr_index: PostOrderId::from_u32(0), - label_stack: vec![], - } - } - - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn record_drop(&mut self, value: TrackedValue) { - if self.places.borrowed.contains(&value) { - debug!("not marking {:?} as dropped because it is borrowed at some point", value); - } else { - debug!("marking {:?} as dropped at {:?}", value, self.expr_index); - let count = self.expr_index; - self.drop_ranges.drop_at(value, count); - } - } - - /// ExprUseVisitor's consume callback doesn't go deep enough for our purposes in all - /// expressions. This method consumes a little deeper into the expression when needed. - fn consume_expr(&mut self, expr: &hir::Expr<'_>) { - debug!("consuming expr {:?}, count={:?}", expr.kind, self.expr_index); - let places = self - .places - .consumed - .get(&expr.hir_id) - .map_or(vec![], |places| places.iter().cloned().collect()); - for place in places { - trace!(?place, "consuming place"); - for_each_consumable(self.tcx().hir(), place, |value| self.record_drop(value)); - } - } - - /// Marks an expression as being reinitialized. - /// - /// Note that we always approximated on the side of things being more - /// initialized than they actually are, as opposed to less. In cases such - /// as `x.y = ...`, we would consider all of `x` as being initialized - /// instead of just the `y` field. - /// - /// This is because it is always safe to consider something initialized - /// even when it is not, but the other way around will cause problems. - /// - /// In the future, we will hopefully tighten up these rules to be more - /// precise. - fn reinit_expr(&mut self, expr: &hir::Expr<'_>) { - // Walk the expression to find the base. For example, in an expression - // like `*a[i].x`, we want to find the `a` and mark that as - // reinitialized. - match expr.kind { - ExprKind::Path(hir::QPath::Resolved( - _, - hir::Path { res: hir::def::Res::Local(hir_id), .. }, - )) => { - // This is the base case, where we have found an actual named variable. - - let location = self.expr_index; - debug!("reinitializing {:?} at {:?}", hir_id, location); - self.drop_ranges.reinit_at(TrackedValue::Variable(*hir_id), location); - } - - ExprKind::Field(base, _) => self.reinit_expr(base), - - // Most expressions do not refer to something where we need to track - // reinitializations. - // - // Some of these may be interesting in the future - ExprKind::Path(..) - | ExprKind::ConstBlock(..) - | ExprKind::Array(..) - | ExprKind::Call(..) - | ExprKind::MethodCall(..) - | ExprKind::Tup(..) - | ExprKind::Binary(..) - | ExprKind::Unary(..) - | ExprKind::Lit(..) - | ExprKind::Cast(..) - | ExprKind::Type(..) - | ExprKind::DropTemps(..) - | ExprKind::Let(..) - | ExprKind::If(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - | ExprKind::Closure { .. } - | ExprKind::Block(..) - | ExprKind::Assign(..) - | ExprKind::AssignOp(..) - | ExprKind::Index(..) - | ExprKind::AddrOf(..) - | ExprKind::Break(..) - | ExprKind::Continue(..) - | ExprKind::Ret(..) - | ExprKind::Become(..) - | ExprKind::InlineAsm(..) - | ExprKind::OffsetOf(..) - | ExprKind::Struct(..) - | ExprKind::Repeat(..) - | ExprKind::Yield(..) - | ExprKind::Err(_) => (), - } - } - - /// For an expression with an uninhabited return type (e.g. a function that returns !), - /// this adds a self edge to the CFG to model the fact that the function does not - /// return. - fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) { - let ty = self.typeck_results.expr_ty(expr); - let ty = self.infcx.resolve_vars_if_possible(ty); - if ty.has_non_region_infer() { - self.tcx() - .sess - .delay_span_bug(expr.span, format!("could not resolve infer vars in `{ty}`")); - return; - } - let ty = self.tcx().erase_regions(ty); - let m = self.tcx().parent_module(expr.hir_id).to_def_id(); - if !ty.is_inhabited_from(self.tcx(), m, self.param_env) { - // This function will not return. We model this fact as an infinite loop. - self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1); - } - } - - /// Map a Destination to an equivalent expression node - /// - /// The destination field of a Break or Continue expression can target either an - /// expression or a block. The drop range analysis, however, only deals in - /// expression nodes, so blocks that might be the destination of a Break or Continue - /// will not have a PostOrderId. - /// - /// If the destination is an expression, this function will simply return that expression's - /// hir_id. If the destination is a block, this function will return the hir_id of last - /// expression in the block. - fn find_target_expression_from_destination( - &self, - destination: hir::Destination, - ) -> Result { - destination.target_id.map(|target| { - let node = self.tcx().hir().get(target); - match node { - hir::Node::Expr(_) => target, - hir::Node::Block(b) => find_last_block_expression(b), - hir::Node::Param(..) - | hir::Node::Item(..) - | hir::Node::ForeignItem(..) - | hir::Node::TraitItem(..) - | hir::Node::ImplItem(..) - | hir::Node::Variant(..) - | hir::Node::Field(..) - | hir::Node::AnonConst(..) - | hir::Node::ConstBlock(..) - | hir::Node::Stmt(..) - | hir::Node::PathSegment(..) - | hir::Node::Ty(..) - | hir::Node::TypeBinding(..) - | hir::Node::TraitRef(..) - | hir::Node::Pat(..) - | hir::Node::PatField(..) - | hir::Node::ExprField(..) - | hir::Node::Arm(..) - | hir::Node::Local(..) - | hir::Node::Ctor(..) - | hir::Node::Lifetime(..) - | hir::Node::GenericParam(..) - | hir::Node::Crate(..) - | hir::Node::Infer(..) => bug!("Unsupported branch target: {:?}", node), - } - }) - } -} - -fn find_last_block_expression(block: &hir::Block<'_>) -> HirId { - block.expr.map_or_else( - // If there is no tail expression, there will be at least one statement in the - // block because the block contains a break or continue statement. - || block.stmts.last().unwrap().hir_id, - |expr| expr.hir_id, - ) -} - -impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - let mut reinit = None; - match expr.kind { - ExprKind::Assign(lhs, rhs, _) => { - self.visit_expr(rhs); - self.visit_expr(lhs); - - reinit = Some(lhs); - } - - ExprKind::If(test, if_true, if_false) => { - self.visit_expr(test); - - let fork = self.expr_index; - - self.drop_ranges.add_control_edge(fork, self.expr_index + 1); - self.visit_expr(if_true); - let true_end = self.expr_index; - - self.drop_ranges.add_control_edge(fork, self.expr_index + 1); - if let Some(if_false) = if_false { - self.visit_expr(if_false); - } - - self.drop_ranges.add_control_edge(true_end, self.expr_index + 1); - } - ExprKind::Match(scrutinee, arms, ..) => { - // We walk through the match expression almost like a chain of if expressions. - // Here's a diagram to follow along with: - // - // ┌─┐ - // match │A│ { - // ┌───┴─┘ - // │ - // ┌▼┌───►┌─┐ ┌─┐ - // │B│ if │C│ =>│D│, - // └─┘ ├─┴──►└─┴──────┐ - // ┌──┘ │ - // ┌──┘ │ - // │ │ - // ┌▼┌───►┌─┐ ┌─┐ │ - // │E│ if │F│ =>│G│, │ - // └─┘ ├─┴──►└─┴┐ │ - // │ │ │ - // } ▼ ▼ │ - // ┌─┐◄───────────────────┘ - // │H│ - // └─┘ - // - // The order we want is that the scrutinee (A) flows into the first pattern (B), - // which flows into the guard (C). Then the guard either flows into the arm body - // (D) or into the start of the next arm (E). Finally, the body flows to the end - // of the match block (H). - // - // The subsequent arms follow the same ordering. First we go to the pattern, then - // the guard (if present, otherwise it flows straight into the body), then into - // the body and then to the end of the match expression. - // - // The comments below show which edge is being added. - self.visit_expr(scrutinee); - - let (guard_exit, arm_end_ids) = arms.iter().fold( - (self.expr_index, vec![]), - |(incoming_edge, mut arm_end_ids), hir::Arm { pat, body, guard, .. }| { - // A -> B, or C -> E - self.drop_ranges.add_control_edge(incoming_edge, self.expr_index + 1); - self.visit_pat(pat); - // B -> C and E -> F are added implicitly due to the traversal order. - match guard { - Some(Guard::If(expr)) => self.visit_expr(expr), - Some(Guard::IfLet(let_expr)) => { - self.visit_let_expr(let_expr); - } - None => (), - } - // Likewise, C -> D and F -> G are added implicitly. - - // Save C, F, so we can add the other outgoing edge. - let to_next_arm = self.expr_index; - - // The default edge does not get added since we also have an explicit edge, - // so we also need to add an edge to the next node as well. - // - // This adds C -> D, F -> G - self.drop_ranges.add_control_edge(self.expr_index, self.expr_index + 1); - self.visit_expr(body); - - // Save the end of the body so we can add the exit edge once we know where - // the exit is. - arm_end_ids.push(self.expr_index); - - // Pass C to the next iteration, as well as vec![D] - // - // On the last round through, we pass F and vec![D, G] so that we can - // add all the exit edges. - (to_next_arm, arm_end_ids) - }, - ); - // F -> H - self.drop_ranges.add_control_edge(guard_exit, self.expr_index + 1); - - arm_end_ids.into_iter().for_each(|arm_end| { - // D -> H, G -> H - self.drop_ranges.add_control_edge(arm_end, self.expr_index + 1) - }); - } - - ExprKind::Loop(body, label, ..) => { - let loop_begin = self.expr_index + 1; - self.label_stack.push((label, loop_begin)); - if body.stmts.is_empty() && body.expr.is_none() { - // For empty loops we won't have updated self.expr_index after visiting the - // body, meaning we'd get an edge from expr_index to expr_index + 1, but - // instead we want an edge from expr_index + 1 to expr_index + 1. - self.drop_ranges.add_control_edge(loop_begin, loop_begin); - } else { - self.visit_block(body); - self.drop_ranges.add_control_edge(self.expr_index, loop_begin); - } - self.label_stack.pop(); - } - // Find the loop entry by searching through the label stack for either the last entry - // (if label is none), or the first entry where the label matches this one. The Loop - // case maintains this stack mapping labels to the PostOrderId for the loop entry. - ExprKind::Continue(hir::Destination { label, .. }, ..) => self - .label_stack - .iter() - .rev() - .find(|(loop_label, _)| label.is_none() || *loop_label == label) - .map_or((), |(_, target)| { - self.drop_ranges.add_control_edge(self.expr_index, *target) - }), - - ExprKind::Break(destination, value) => { - // destination either points to an expression or to a block. We use - // find_target_expression_from_destination to use the last expression of the block - // if destination points to a block. - // - // We add an edge to the hir_id of the expression/block we are breaking out of, and - // then in process_deferred_edges we will map this hir_id to its PostOrderId, which - // will refer to the end of the block due to the post order traversal. - if let Ok(target) = self.find_target_expression_from_destination(destination) { - self.drop_ranges.add_control_edge_hir_id(self.expr_index, target) - } - - if let Some(value) = value { - self.visit_expr(value); - } - } - - ExprKind::Become(_call) => bug!("encountered a tail-call inside a generator"), - - ExprKind::Call(f, args) => { - self.visit_expr(f); - for arg in args { - self.visit_expr(arg); - } - - self.handle_uninhabited_return(expr); - } - ExprKind::MethodCall(_, receiver, exprs, _) => { - self.visit_expr(receiver); - for expr in exprs { - self.visit_expr(expr); - } - - self.handle_uninhabited_return(expr); - } - - ExprKind::AddrOf(..) - | ExprKind::Array(..) - // FIXME(eholk): We probably need special handling for AssignOps. The ScopeTree builder - // in region.rs runs both lhs then rhs and rhs then lhs and then sets all yields to be - // the latest they show up in either traversal. With the older scope-based - // approximation, this was fine, but it's probably not right now. What we probably want - // to do instead is still run both orders, but consider anything that showed up as a - // yield in either order. - | ExprKind::AssignOp(..) - | ExprKind::Binary(..) - | ExprKind::Block(..) - | ExprKind::Cast(..) - | ExprKind::Closure { .. } - | ExprKind::ConstBlock(..) - | ExprKind::DropTemps(..) - | ExprKind::Err(_) - | ExprKind::Field(..) - | ExprKind::Index(..) - | ExprKind::InlineAsm(..) - | ExprKind::OffsetOf(..) - | ExprKind::Let(..) - | ExprKind::Lit(..) - | ExprKind::Path(..) - | ExprKind::Repeat(..) - | ExprKind::Ret(..) - | ExprKind::Struct(..) - | ExprKind::Tup(..) - | ExprKind::Type(..) - | ExprKind::Unary(..) - | ExprKind::Yield(..) => intravisit::walk_expr(self, expr), - } - - self.expr_index = self.expr_index + 1; - self.drop_ranges.add_node_mapping(expr.hir_id, self.expr_index); - self.consume_expr(expr); - if let Some(expr) = reinit { - self.reinit_expr(expr); - } - } - - fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { - intravisit::walk_pat(self, pat); - - // Increment expr_count here to match what InteriorVisitor expects. - self.expr_index = self.expr_index + 1; - - // Save a node mapping to get better CFG visualization - self.drop_ranges.add_node_mapping(pat.hir_id, self.expr_index); - } -} - -impl DropRangesBuilder { - fn new( - tracked_values: impl Iterator, - hir: Map<'_>, - num_exprs: usize, - ) -> Self { - let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default(); - let mut next = <_>::from(0u32); - for value in tracked_values { - for_each_consumable(hir, value, |value| { - if let std::collections::hash_map::Entry::Vacant(e) = tracked_value_map.entry(value) - { - e.insert(next); - next = next + 1; - } - }); - } - debug!("hir_id_map: {:#?}", tracked_value_map); - let num_values = tracked_value_map.len(); - Self { - tracked_value_map, - nodes: IndexVec::from_fn_n(|_| NodeInfo::new(num_values), num_exprs + 1), - deferred_edges: <_>::default(), - post_order_map: <_>::default(), - } - } - - fn tracked_value_index(&self, tracked_value: TrackedValue) -> TrackedValueIndex { - *self.tracked_value_map.get(&tracked_value).unwrap() - } - - /// Adds an entry in the mapping from HirIds to PostOrderIds - /// - /// Needed so that `add_control_edge_hir_id` can work. - fn add_node_mapping(&mut self, node_hir_id: HirId, post_order_id: PostOrderId) { - self.post_order_map.insert(node_hir_id, post_order_id); - } - - /// Like add_control_edge, but uses a hir_id as the target. - /// - /// This can be used for branches where we do not know the PostOrderId of the target yet, - /// such as when handling `break` or `continue`. - fn add_control_edge_hir_id(&mut self, from: PostOrderId, to: HirId) { - self.deferred_edges.push((from, to)); - } - - fn drop_at(&mut self, value: TrackedValue, location: PostOrderId) { - let value = self.tracked_value_index(value); - self.node_mut(location).drops.push(value); - } - - fn reinit_at(&mut self, value: TrackedValue, location: PostOrderId) { - let value = match self.tracked_value_map.get(&value) { - Some(value) => *value, - // If there's no value, this is never consumed and therefore is never dropped. We can - // ignore this. - None => return, - }; - self.node_mut(location).reinits.push(value); - } - - /// Looks up PostOrderId for any control edges added by HirId and adds a proper edge for them. - /// - /// Should be called after visiting the HIR but before solving the control flow, otherwise some - /// edges will be missed. - fn process_deferred_edges(&mut self) { - trace!("processing deferred edges. post_order_map={:#?}", self.post_order_map); - let mut edges = vec![]; - swap(&mut edges, &mut self.deferred_edges); - edges.into_iter().for_each(|(from, to)| { - trace!("Adding deferred edge from {:?} to {:?}", from, to); - let to = *self.post_order_map.get(&to).expect("Expression ID not found"); - trace!("target edge PostOrderId={:?}", to); - self.add_control_edge(from, to) - }); - } -} diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs deleted file mode 100644 index 633b478895b10..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs +++ /dev/null @@ -1,92 +0,0 @@ -use super::{DropRangesBuilder, PostOrderId}; -use rustc_index::{bit_set::BitSet, IndexVec}; -use std::collections::BTreeMap; - -impl DropRangesBuilder { - pub fn propagate_to_fixpoint(&mut self) { - trace!("before fixpoint: {:#?}", self); - let preds = self.compute_predecessors(); - - trace!("predecessors: {:#?}", preds.iter_enumerated().collect::>()); - - let mut new_state = BitSet::new_empty(self.num_values()); - let mut changed_nodes = BitSet::new_empty(self.nodes.len()); - let mut unchanged_mask = BitSet::new_filled(self.nodes.len()); - changed_nodes.insert(0u32.into()); - - let mut propagate = || { - let mut changed = false; - unchanged_mask.insert_all(); - for id in self.nodes.indices() { - trace!("processing {:?}, changed_nodes: {:?}", id, changed_nodes); - // Check if any predecessor has changed, and if not then short-circuit. - // - // We handle the start node specially, since it doesn't have any predecessors, - // but we need to start somewhere. - if match id.index() { - 0 => !changed_nodes.contains(id), - _ => !preds[id].iter().any(|pred| changed_nodes.contains(*pred)), - } { - trace!("short-circuiting because none of {:?} have changed", preds[id]); - unchanged_mask.remove(id); - continue; - } - - if id.index() == 0 { - new_state.clear(); - } else { - // If we are not the start node and we have no predecessors, treat - // everything as dropped because there's no way to get here anyway. - new_state.insert_all(); - }; - - for pred in &preds[id] { - new_state.intersect(&self.nodes[*pred].drop_state); - } - - for drop in &self.nodes[id].drops { - new_state.insert(*drop); - } - - for reinit in &self.nodes[id].reinits { - new_state.remove(*reinit); - } - - if self.nodes[id].drop_state.intersect(&new_state) { - changed_nodes.insert(id); - changed = true; - } else { - unchanged_mask.remove(id); - } - } - - changed_nodes.intersect(&unchanged_mask); - changed - }; - - while propagate() { - trace!("drop_state changed, re-running propagation"); - } - - trace!("after fixpoint: {:#?}", self); - } - - fn compute_predecessors(&self) -> IndexVec> { - let mut preds = IndexVec::from_fn_n(|_| vec![], self.nodes.len()); - for (id, node) in self.nodes.iter_enumerated() { - // If the node has no explicit successors, we assume that control - // will from this node into the next one. - // - // If there are successors listed, then we assume that all - // possible successors are given and we do not include the default. - if node.successors.len() == 0 && id.index() != self.nodes.len() - 1 { - preds[id + 1].push(id); - } else { - for succ in &node.successors { - preds[*succ].push(id); - } - } - } - preds - } -} diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs deleted file mode 100644 index e8d31be79d9c9..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Implementation of GraphWalk for DropRanges so we can visualize the control -//! flow graph when needed for debugging. - -use rustc_graphviz as dot; -use rustc_hir::{Expr, ExprKind, Node}; -use rustc_middle::ty::TyCtxt; - -use super::{DropRangesBuilder, PostOrderId}; - -/// Writes the CFG for DropRangesBuilder to a .dot file for visualization. -/// -/// It is not normally called, but is kept around to easily add debugging -/// code when needed. -pub(super) fn write_graph_to_file( - drop_ranges: &DropRangesBuilder, - filename: &str, - tcx: TyCtxt<'_>, -) { - dot::render( - &DropRangesGraph { drop_ranges, tcx }, - &mut std::fs::File::create(filename).unwrap(), - ) - .unwrap(); -} - -struct DropRangesGraph<'a, 'tcx> { - drop_ranges: &'a DropRangesBuilder, - tcx: TyCtxt<'tcx>, -} - -impl<'a> dot::GraphWalk<'a> for DropRangesGraph<'_, '_> { - type Node = PostOrderId; - - type Edge = (PostOrderId, PostOrderId); - - fn nodes(&'a self) -> dot::Nodes<'a, Self::Node> { - self.drop_ranges.nodes.iter_enumerated().map(|(i, _)| i).collect() - } - - fn edges(&'a self) -> dot::Edges<'a, Self::Edge> { - self.drop_ranges - .nodes - .iter_enumerated() - .flat_map(|(i, node)| { - if node.successors.len() == 0 { - vec![(i, i + 1)] - } else { - node.successors.iter().map(move |&s| (i, s)).collect() - } - }) - .collect() - } - - fn source(&'a self, edge: &Self::Edge) -> Self::Node { - edge.0 - } - - fn target(&'a self, edge: &Self::Edge) -> Self::Node { - edge.1 - } -} - -impl<'a> dot::Labeller<'a> for DropRangesGraph<'_, '_> { - type Node = PostOrderId; - - type Edge = (PostOrderId, PostOrderId); - - fn graph_id(&'a self) -> dot::Id<'a> { - dot::Id::new("drop_ranges").unwrap() - } - - fn node_id(&'a self, n: &Self::Node) -> dot::Id<'a> { - dot::Id::new(format!("id{}", n.index())).unwrap() - } - - fn node_label(&'a self, n: &Self::Node) -> dot::LabelText<'a> { - dot::LabelText::LabelStr( - format!( - "{n:?}: {}", - self.drop_ranges - .post_order_map - .iter() - .find(|(_hir_id, &post_order_id)| post_order_id == *n) - .map_or("".into(), |(hir_id, _)| format!( - "{}{}", - self.tcx.hir().node_to_string(*hir_id), - match self.tcx.hir().find(*hir_id) { - Some(Node::Expr(Expr { kind: ExprKind::Yield(..), .. })) => " (yield)", - _ => "", - } - )) - ) - .into(), - ) - } -} diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs deleted file mode 100644 index e563bd40b6542..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs +++ /dev/null @@ -1,306 +0,0 @@ -//! Drop range analysis finds the portions of the tree where a value is guaranteed to be dropped -//! (i.e. moved, uninitialized, etc.). This is used to exclude the types of those values from the -//! generator type. See `InteriorVisitor::record` for where the results of this analysis are used. -//! -//! There are three phases to this analysis: -//! 1. Use `ExprUseVisitor` to identify the interesting values that are consumed and borrowed. -//! 2. Use `DropRangeVisitor` to find where the interesting values are dropped or reinitialized, -//! and also build a control flow graph. -//! 3. Use `DropRanges::propagate_to_fixpoint` to flow the dropped/reinitialized information through -//! the CFG and find the exact points where we know a value is definitely dropped. -//! -//! The end result is a data structure that maps the post-order index of each node in the HIR tree -//! to a set of values that are known to be dropped at that location. - -use self::cfg_build::build_control_flow_graph; -use self::record_consumed_borrow::find_consumed_and_borrowed; -use crate::FnCtxt; -use hir::def_id::DefId; -use hir::{Body, HirId, HirIdMap, Node}; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_hir as hir; -use rustc_index::bit_set::BitSet; -use rustc_index::IndexVec; -use rustc_middle::hir::map::Map; -use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; -use rustc_middle::ty; -use std::collections::BTreeMap; -use std::fmt::Debug; - -mod cfg_build; -mod cfg_propagate; -mod cfg_visualize; -mod record_consumed_borrow; - -pub fn compute_drop_ranges<'a, 'tcx>( - fcx: &'a FnCtxt<'a, 'tcx>, - def_id: DefId, - body: &'tcx Body<'tcx>, -) -> DropRanges { - if fcx.sess().opts.unstable_opts.drop_tracking { - let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body); - - let typeck_results = &fcx.typeck_results.borrow(); - let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0); - let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph( - &fcx, - typeck_results, - fcx.param_env, - consumed_borrowed_places, - body, - num_exprs, - ); - - drop_ranges.propagate_to_fixpoint(); - - debug!("borrowed_temporaries = {borrowed_temporaries:?}"); - DropRanges { - tracked_value_map: drop_ranges.tracked_value_map, - nodes: drop_ranges.nodes, - borrowed_temporaries: Some(borrowed_temporaries), - } - } else { - // If drop range tracking is not enabled, skip all the analysis and produce an - // empty set of DropRanges. - DropRanges { - tracked_value_map: UnordMap::default(), - nodes: IndexVec::new(), - borrowed_temporaries: None, - } - } -} - -/// Applies `f` to consumable node in the HIR subtree pointed to by `place`. -/// -/// This includes the place itself, and if the place is a reference to a local -/// variable then `f` is also called on the HIR node for that variable as well. -/// -/// For example, if `place` points to `foo()`, then `f` is called once for the -/// result of `foo`. On the other hand, if `place` points to `x` then `f` will -/// be called both on the `ExprKind::Path` node that represents the expression -/// as well as the HirId of the local `x` itself. -fn for_each_consumable(hir: Map<'_>, place: TrackedValue, mut f: impl FnMut(TrackedValue)) { - f(place); - let node = hir.find(place.hir_id()); - if let Some(Node::Expr(expr)) = node { - match expr.kind { - hir::ExprKind::Path(hir::QPath::Resolved( - _, - hir::Path { res: hir::def::Res::Local(hir_id), .. }, - )) => { - f(TrackedValue::Variable(*hir_id)); - } - _ => (), - } - } -} - -rustc_index::newtype_index! { - #[debug_format = "id({})"] - pub struct PostOrderId {} -} - -rustc_index::newtype_index! { - #[debug_format = "hidx({})"] - pub struct TrackedValueIndex {} -} - -/// Identifies a value whose drop state we need to track. -#[derive(PartialEq, Eq, Hash, Clone, Copy)] -enum TrackedValue { - /// Represents a named variable, such as a let binding, parameter, or upvar. - /// - /// The HirId points to the variable's definition site. - Variable(HirId), - /// A value produced as a result of an expression. - /// - /// The HirId points to the expression that returns this value. - Temporary(HirId), -} - -impl Debug for TrackedValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ty::tls::with_opt(|opt_tcx| { - if let Some(tcx) = opt_tcx { - write!(f, "{}", tcx.hir().node_to_string(self.hir_id())) - } else { - match self { - Self::Variable(hir_id) => write!(f, "Variable({hir_id:?})"), - Self::Temporary(hir_id) => write!(f, "Temporary({hir_id:?})"), - } - } - }) - } -} - -impl TrackedValue { - fn hir_id(&self) -> HirId { - match self { - TrackedValue::Variable(hir_id) | TrackedValue::Temporary(hir_id) => *hir_id, - } - } - - fn from_place_with_projections_allowed(place_with_id: &PlaceWithHirId<'_>) -> Self { - match place_with_id.place.base { - PlaceBase::Rvalue | PlaceBase::StaticItem => { - TrackedValue::Temporary(place_with_id.hir_id) - } - PlaceBase::Local(hir_id) - | PlaceBase::Upvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id }, .. }) => { - TrackedValue::Variable(hir_id) - } - } - } -} - -/// Represents a reason why we might not be able to convert a HirId or Place -/// into a tracked value. -#[derive(Debug)] -enum TrackedValueConversionError { - /// Place projects are not currently supported. - /// - /// The reasoning around these is kind of subtle, so we choose to be more - /// conservative around these for now. There is no reason in theory we - /// cannot support these, we just have not implemented it yet. - PlaceProjectionsNotSupported, -} - -impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue { - type Error = TrackedValueConversionError; - - fn try_from(place_with_id: &PlaceWithHirId<'_>) -> Result { - if !place_with_id.place.projections.is_empty() { - debug!( - "TrackedValue from PlaceWithHirId: {:?} has projections, which are not supported.", - place_with_id - ); - return Err(TrackedValueConversionError::PlaceProjectionsNotSupported); - } - - Ok(TrackedValue::from_place_with_projections_allowed(place_with_id)) - } -} - -pub struct DropRanges { - tracked_value_map: UnordMap, - nodes: IndexVec, - borrowed_temporaries: Option>, -} - -impl DropRanges { - pub fn is_dropped_at(&self, hir_id: HirId, location: usize) -> bool { - self.tracked_value_map - .get(&TrackedValue::Temporary(hir_id)) - .or(self.tracked_value_map.get(&TrackedValue::Variable(hir_id))) - .cloned() - .is_some_and(|tracked_value_id| { - self.expect_node(location.into()).drop_state.contains(tracked_value_id) - }) - } - - pub fn is_borrowed_temporary(&self, expr: &hir::Expr<'_>) -> bool { - if let Some(b) = &self.borrowed_temporaries { b.contains(&expr.hir_id) } else { true } - } - - /// Returns a reference to the NodeInfo for a node, panicking if it does not exist - fn expect_node(&self, id: PostOrderId) -> &NodeInfo { - &self.nodes[id] - } -} - -/// Tracks information needed to compute drop ranges. -struct DropRangesBuilder { - /// The core of DropRangesBuilder is a set of nodes, which each represent - /// one expression. We primarily refer to them by their index in a - /// post-order traversal of the HIR tree, since this is what - /// generator_interior uses to talk about yield positions. - /// - /// This IndexVec keeps the relevant details for each node. See the - /// NodeInfo struct for more details, but this information includes things - /// such as the set of control-flow successors, which variables are dropped - /// or reinitialized, and whether each variable has been inferred to be - /// known-dropped or potentially reinitialized at each point. - nodes: IndexVec, - /// We refer to values whose drop state we are tracking by the HirId of - /// where they are defined. Within a NodeInfo, however, we store the - /// drop-state in a bit vector indexed by a HirIdIndex - /// (see NodeInfo::drop_state). The hir_id_map field stores the mapping - /// from HirIds to the HirIdIndex that is used to represent that value in - /// bitvector. - tracked_value_map: UnordMap, - - /// When building the control flow graph, we don't always know the - /// post-order index of the target node at the point we encounter it. - /// For example, this happens with break and continue. In those cases, - /// we store a pair of the PostOrderId of the source and the HirId - /// of the target. Once we have gathered all of these edges, we make a - /// pass over the set of deferred edges (see process_deferred_edges in - /// cfg_build.rs), look up the PostOrderId for the target (since now the - /// post-order index for all nodes is known), and add missing control flow - /// edges. - deferred_edges: Vec<(PostOrderId, HirId)>, - /// This maps HirIds of expressions to their post-order index. It is - /// used in process_deferred_edges to correctly add back-edges. - post_order_map: HirIdMap, -} - -impl Debug for DropRangesBuilder { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("DropRanges") - .field("hir_id_map", &self.tracked_value_map) - .field("post_order_maps", &self.post_order_map) - .field("nodes", &self.nodes.iter_enumerated().collect::>()) - .finish() - } -} - -/// DropRanges keeps track of what values are definitely dropped at each point in the code. -/// -/// Values of interest are defined by the hir_id of their place. Locations in code are identified -/// by their index in the post-order traversal. At its core, DropRanges maps -/// (hir_id, post_order_id) -> bool, where a true value indicates that the value is definitely -/// dropped at the point of the node identified by post_order_id. -impl DropRangesBuilder { - /// Returns the number of values (hir_ids) that are tracked - fn num_values(&self) -> usize { - self.tracked_value_map.len() - } - - fn node_mut(&mut self, id: PostOrderId) -> &mut NodeInfo { - let size = self.num_values(); - self.nodes.ensure_contains_elem(id, || NodeInfo::new(size)) - } - - fn add_control_edge(&mut self, from: PostOrderId, to: PostOrderId) { - trace!("adding control edge from {:?} to {:?}", from, to); - self.node_mut(from).successors.push(to); - } -} - -#[derive(Debug)] -struct NodeInfo { - /// IDs of nodes that can follow this one in the control flow - /// - /// If the vec is empty, then control proceeds to the next node. - successors: Vec, - - /// List of hir_ids that are dropped by this node. - drops: Vec, - - /// List of hir_ids that are reinitialized by this node. - reinits: Vec, - - /// Set of values that are definitely dropped at this point. - drop_state: BitSet, -} - -impl NodeInfo { - fn new(num_values: usize) -> Self { - Self { - successors: vec![], - drops: vec![], - reinits: vec![], - drop_state: BitSet::new_filled(num_values), - } - } -} diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs deleted file mode 100644 index 29413f0801237..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs +++ /dev/null @@ -1,242 +0,0 @@ -use super::TrackedValue; -use crate::{ - expr_use_visitor::{self, ExprUseVisitor}, - FnCtxt, -}; -use hir::{def_id::DefId, Body, HirId, HirIdMap}; -use rustc_data_structures::{fx::FxIndexSet, unord::UnordSet}; -use rustc_hir as hir; -use rustc_middle::ty::{ParamEnv, TyCtxt}; -use rustc_middle::{ - hir::place::{PlaceBase, Projection, ProjectionKind}, - ty::TypeVisitableExt, -}; - -pub(super) fn find_consumed_and_borrowed<'a, 'tcx>( - fcx: &'a FnCtxt<'a, 'tcx>, - def_id: DefId, - body: &'tcx Body<'tcx>, -) -> ConsumedAndBorrowedPlaces { - let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx, fcx.param_env); - expr_use_visitor.consume_body(fcx, def_id, body); - expr_use_visitor.places -} - -pub(super) struct ConsumedAndBorrowedPlaces { - /// Records the variables/expressions that are dropped by a given expression. - /// - /// The key is the hir-id of the expression, and the value is a set or hir-ids for variables - /// or values that are consumed by that expression. - /// - /// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is - /// not considered a drop of `x`, although it would be a drop of `x.y`. - pub(super) consumed: HirIdMap>, - - /// A set of hir-ids of values or variables that are borrowed at some point within the body. - pub(super) borrowed: UnordSet, - - /// A set of hir-ids of values or variables that are borrowed at some point within the body. - pub(super) borrowed_temporaries: UnordSet, -} - -/// Works with ExprUseVisitor to find interesting values for the drop range analysis. -/// -/// Interesting values are those that are either dropped or borrowed. For dropped values, we also -/// record the parent expression, which is the point where the drop actually takes place. -struct ExprUseDelegate<'tcx> { - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - places: ConsumedAndBorrowedPlaces, -} - -impl<'tcx> ExprUseDelegate<'tcx> { - fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { - Self { - tcx, - param_env, - places: ConsumedAndBorrowedPlaces { - consumed: <_>::default(), - borrowed: <_>::default(), - borrowed_temporaries: <_>::default(), - }, - } - } - - fn consume_body(&mut self, fcx: &'_ FnCtxt<'_, 'tcx>, def_id: DefId, body: &'tcx Body<'tcx>) { - // Run ExprUseVisitor to find where values are consumed. - ExprUseVisitor::new( - self, - &fcx.infcx, - def_id.expect_local(), - fcx.param_env, - &fcx.typeck_results.borrow(), - ) - .consume_body(body); - } - - fn mark_consumed(&mut self, consumer: HirId, target: TrackedValue) { - self.places.consumed.entry(consumer).or_insert_with(|| <_>::default()); - - debug!(?consumer, ?target, "mark_consumed"); - self.places.consumed.get_mut(&consumer).map(|places| places.insert(target)); - } - - fn borrow_place(&mut self, place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>) { - self.places - .borrowed - .insert(TrackedValue::from_place_with_projections_allowed(place_with_id)); - - // Ordinarily a value is consumed by it's parent, but in the special case of a - // borrowed RValue, we create a reference that lives as long as the temporary scope - // for that expression (typically, the innermost statement, but sometimes the enclosing - // block). We record this fact here so that later in generator_interior - // we can use the correct scope. - // - // We special case borrows through a dereference (`&*x`, `&mut *x` where `x` is - // some rvalue expression), since these are essentially a copy of a pointer. - // In other words, this borrow does not refer to the - // temporary (`*x`), but to the referent (whatever `x` is a borrow of). - // - // We were considering that we might encounter problems down the line if somehow, - // some part of the compiler were to look at this result and try to use it to - // drive a borrowck-like analysis (this does not currently happen, as of this writing). - // But even this should be fine, because the lifetime of the dereferenced reference - // found in the rvalue is only significant as an intermediate 'link' to the value we - // are producing, and we separately track whether that value is live over a yield. - // Example: - // - // ```notrust - // fn identity(x: &mut T) -> &mut T { x } - // let a: A = ...; - // let y: &'y mut A = &mut *identity(&'a mut a); - // ^^^^^^^^^^^^^^^^^^^^^^^^^ the borrow we are talking about - // ``` - // - // The expression `*identity(...)` is a deref of an rvalue, - // where the `identity(...)` (the rvalue) produces a return type - // of `&'rv mut A`, where `'a: 'rv`. We then assign this result to - // `'y`, resulting in (transitively) `'a: 'y` (i.e., while `y` is in use, - // `a` will be considered borrowed). Other parts of the code will ensure - // that if `y` is live over a yield, `&'y mut A` appears in the generator - // state. If `'y` is live, then any sound region analysis must conclude - // that `'a` is also live. So if this causes a bug, blame some other - // part of the code! - let is_deref = place_with_id - .place - .projections - .iter() - .any(|Projection { kind, .. }| *kind == ProjectionKind::Deref); - - if let (false, PlaceBase::Rvalue) = (is_deref, place_with_id.place.base) { - self.places.borrowed_temporaries.insert(place_with_id.hir_id); - } - } -} - -impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { - fn consume( - &mut self, - place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, - diag_expr_id: HirId, - ) { - let hir = self.tcx.hir(); - let parent = match hir.opt_parent_id(place_with_id.hir_id) { - Some(parent) => parent, - None => place_with_id.hir_id, - }; - debug!( - "consume {:?}; diag_expr_id={}, using parent {}", - place_with_id, - hir.node_to_string(diag_expr_id), - hir.node_to_string(parent) - ); - - if let Ok(tracked_value) = place_with_id.try_into() { - self.mark_consumed(parent, tracked_value) - } - } - - fn borrow( - &mut self, - place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, - diag_expr_id: HirId, - bk: rustc_middle::ty::BorrowKind, - ) { - debug!( - "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \ - borrow_kind={bk:#?}" - ); - - self.borrow_place(place_with_id); - } - - fn copy( - &mut self, - place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, - _diag_expr_id: HirId, - ) { - debug!("copy: place_with_id = {place_with_id:?}"); - - self.places - .borrowed - .insert(TrackedValue::from_place_with_projections_allowed(place_with_id)); - - // For copied we treat this mostly like a borrow except that we don't add the place - // to borrowed_temporaries because the copy is consumed. - } - - fn mutate( - &mut self, - assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>, - diag_expr_id: HirId, - ) { - debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}"); - - if assignee_place.place.base == PlaceBase::Rvalue - && assignee_place.place.projections.is_empty() - { - // Assigning to an Rvalue is illegal unless done through a dereference. We would have - // already gotten a type error, so we will just return here. - return; - } - - // If the type being assigned needs dropped, then the mutation counts as a borrow - // since it is essentially doing `Drop::drop(&mut x); x = new_value;`. - let ty = self.tcx.erase_regions(assignee_place.place.base_ty); - if ty.has_infer() { - self.tcx.sess.delay_span_bug( - self.tcx.hir().span(assignee_place.hir_id), - format!("inference variables in {ty}"), - ); - } else if ty.needs_drop(self.tcx, self.param_env) { - self.places - .borrowed - .insert(TrackedValue::from_place_with_projections_allowed(assignee_place)); - } - } - - fn bind( - &mut self, - binding_place: &expr_use_visitor::PlaceWithHirId<'tcx>, - diag_expr_id: HirId, - ) { - debug!("bind {binding_place:?}; diag_expr_id={diag_expr_id:?}"); - } - - fn fake_read( - &mut self, - place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, - cause: rustc_middle::mir::FakeReadCause, - diag_expr_id: HirId, - ) { - debug!( - "fake_read place_with_id={place_with_id:?}; cause={cause:?}; diag_expr_id={diag_expr_id:?}" - ); - - // fake reads happen in places like the scrutinee of a match expression. - // we treat those as a borrow, much like a copy: the idea is that we are - // transiently creating a `&T` ref that we can read from to observe the current - // value (this `&T` is immediately dropped afterwards). - self.borrow_place(place_with_id); - } -} diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs deleted file mode 100644 index 566dc09cdd250..0000000000000 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ /dev/null @@ -1,711 +0,0 @@ -//! This calculates the types which has storage which lives across a suspension point in a -//! generator from the perspective of typeck. The actual types used at runtime -//! is calculated in `rustc_mir_transform::generator` and may be a subset of the -//! types computed here. - -use self::drop_ranges::DropRanges; -use super::FnCtxt; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_errors::{pluralize, DelayDm}; -use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::DefId; -use rustc_hir::hir_id::HirIdSet; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; -use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin}; -use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; -use rustc_middle::ty::fold::FnMutDelegate; -use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::symbol::sym; -use rustc_span::Span; -use smallvec::{smallvec, SmallVec}; - -mod drop_ranges; - -struct InteriorVisitor<'a, 'tcx> { - fcx: &'a FnCtxt<'a, 'tcx>, - region_scope_tree: &'a region::ScopeTree, - types: FxIndexSet>, - rvalue_scopes: &'a RvalueScopes, - expr_count: usize, - kind: hir::GeneratorKind, - prev_unresolved_span: Option, - linted_values: HirIdSet, - drop_ranges: DropRanges, -} - -impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { - fn record( - &mut self, - ty: Ty<'tcx>, - hir_id: HirId, - scope: Option, - expr: Option<&'tcx Expr<'tcx>>, - source_span: Span, - ) { - use rustc_span::DUMMY_SP; - - let ty = self.fcx.resolve_vars_if_possible(ty); - - debug!( - "attempting to record type ty={:?}; hir_id={:?}; scope={:?}; expr={:?}; source_span={:?}; expr_count={:?}", - ty, hir_id, scope, expr, source_span, self.expr_count, - ); - - let live_across_yield = scope - .map(|s| { - self.region_scope_tree.yield_in_scope(s).and_then(|yield_data| { - // If we are recording an expression that is the last yield - // in the scope, or that has a postorder CFG index larger - // than the one of all of the yields, then its value can't - // be storage-live (and therefore live) at any of the yields. - // - // See the mega-comment at `yield_in_scope` for a proof. - - yield_data - .iter() - .find(|yield_data| { - debug!( - "comparing counts yield: {} self: {}, source_span = {:?}", - yield_data.expr_and_pat_count, self.expr_count, source_span - ); - - if self - .is_dropped_at_yield_location(hir_id, yield_data.expr_and_pat_count) - { - debug!("value is dropped at yield point; not recording"); - return false; - } - - // If it is a borrowing happening in the guard, - // it needs to be recorded regardless because they - // do live across this yield point. - yield_data.expr_and_pat_count >= self.expr_count - }) - .cloned() - }) - }) - .unwrap_or_else(|| { - Some(YieldData { span: DUMMY_SP, expr_and_pat_count: 0, source: self.kind.into() }) - }); - - if let Some(yield_data) = live_across_yield { - debug!( - "type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}", - expr, scope, ty, self.expr_count, yield_data.span - ); - - if let Some((unresolved_term, unresolved_type_span)) = - self.fcx.first_unresolved_const_or_ty_var(&ty) - { - // If unresolved type isn't a ty_var then unresolved_type_span is None - let span = self - .prev_unresolved_span - .unwrap_or_else(|| unresolved_type_span.unwrap_or(source_span)); - - // If we encounter an int/float variable, then inference fallback didn't - // finish due to some other error. Don't emit spurious additional errors. - if let Some(unresolved_ty) = unresolved_term.ty() - && let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = unresolved_ty.kind() - { - self.fcx - .tcx - .sess - .delay_span_bug(span, format!("Encountered var {unresolved_term:?}")); - } else { - let note = format!( - "the type is part of the {} because of this {}", - self.kind.descr(), - yield_data.source - ); - - self.fcx - .need_type_info_err_in_generator(self.kind, span, unresolved_term) - .span_note(yield_data.span, note) - .emit(); - } - } else { - // Insert the type into the ordered set. - let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); - - if !self.linted_values.contains(&hir_id) { - check_must_not_suspend_ty( - self.fcx, - ty, - hir_id, - SuspendCheckData { - expr, - source_span, - yield_span: yield_data.span, - plural_len: 1, - ..Default::default() - }, - ); - self.linted_values.insert(hir_id); - } - - self.types.insert(ty::GeneratorInteriorTypeCause { - span: source_span, - ty, - scope_span, - yield_span: yield_data.span, - expr: expr.map(|e| e.hir_id), - }); - } - } else { - debug!( - "no type in expr = {:?}, count = {:?}, span = {:?}", - expr, - self.expr_count, - expr.map(|e| e.span) - ); - if let Some((unresolved_type, unresolved_type_span)) = - self.fcx.first_unresolved_const_or_ty_var(&ty) - { - debug!( - "remained unresolved_type = {:?}, unresolved_type_span: {:?}", - unresolved_type, unresolved_type_span - ); - self.prev_unresolved_span = unresolved_type_span; - } - } - } - - /// If drop tracking is enabled, consult drop_ranges to see if a value is - /// known to be dropped at a yield point and therefore can be omitted from - /// the generator witness. - fn is_dropped_at_yield_location(&self, value_hir_id: HirId, yield_location: usize) -> bool { - // short-circuit if drop tracking is not enabled. - if !self.fcx.sess().opts.unstable_opts.drop_tracking { - return false; - } - - self.drop_ranges.is_dropped_at(value_hir_id, yield_location) - } -} - -pub fn resolve_interior<'a, 'tcx>( - fcx: &'a FnCtxt<'a, 'tcx>, - def_id: DefId, - body_id: hir::BodyId, - interior: Ty<'tcx>, - kind: hir::GeneratorKind, -) { - let body = fcx.tcx.hir().body(body_id); - let typeck_results = fcx.inh.typeck_results.borrow(); - let mut visitor = InteriorVisitor { - fcx, - types: FxIndexSet::default(), - region_scope_tree: fcx.tcx.region_scope_tree(def_id), - rvalue_scopes: &typeck_results.rvalue_scopes, - expr_count: 0, - kind, - prev_unresolved_span: None, - linted_values: <_>::default(), - drop_ranges: drop_ranges::compute_drop_ranges(fcx, def_id, body), - }; - intravisit::walk_body(&mut visitor, body); - - // Check that we visited the same amount of expressions as the RegionResolutionVisitor - let region_expr_count = fcx.tcx.region_scope_tree(def_id).body_expr_count(body_id).unwrap(); - assert_eq!(region_expr_count, visitor.expr_count); - - // The types are already kept in insertion order. - let types = visitor.types; - - // The types in the generator interior contain lifetimes local to the generator itself, - // which should not be exposed outside of the generator. Therefore, we replace these - // lifetimes with existentially-bound lifetimes, which reflect the exact value of the - // lifetimes not being known by users. - // - // These lifetimes are used in auto trait impl checking (for example, - // if a Sync generator contains an &'α T, we need to check whether &'α T: Sync), - // so knowledge of the exact relationships between them isn't particularly important. - - debug!("types in generator {:?}, span = {:?}", types, body.value.span); - - // We want to deduplicate if the lifetimes are the same modulo some non-informative counter. - // So, we need to actually do two passes: first by type to anonymize (preserving information - // required for diagnostics), then a second pass over all captured types to reassign disjoint - // region indices. - let mut captured_tys = FxHashSet::default(); - let type_causes: Vec<_> = types - .into_iter() - .filter_map(|mut cause| { - // Replace all regions inside the generator interior with late bound regions. - // Note that each region slot in the types gets a new fresh late bound region, - // which means that none of the regions inside relate to any other, even if - // typeck had previously found constraints that would cause them to be related. - - let mut counter = 0; - let mut mk_bound_region = |kind| { - let var = ty::BoundVar::from_u32(counter); - counter += 1; - ty::BoundRegion { var, kind } - }; - let ty = fcx.normalize(cause.span, cause.ty); - let ty = fcx.tcx.fold_regions(ty, |region, current_depth| { - let br = match region.kind() { - ty::ReVar(vid) => { - let origin = fcx.region_var_origin(vid); - match origin { - RegionVariableOrigin::EarlyBoundRegion(span, _) => { - mk_bound_region(ty::BrAnon(Some(span))) - } - _ => mk_bound_region(ty::BrAnon(None)), - } - } - ty::ReEarlyBound(region) => { - mk_bound_region(ty::BrNamed(region.def_id, region.name)) - } - ty::ReLateBound(_, ty::BoundRegion { kind, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind { - ty::BoundRegionKind::BrAnon(span) => mk_bound_region(ty::BrAnon(span)), - ty::BoundRegionKind::BrNamed(def_id, sym) => { - mk_bound_region(ty::BrNamed(def_id, sym)) - } - ty::BoundRegionKind::BrEnv => mk_bound_region(ty::BrAnon(None)), - }, - _ => mk_bound_region(ty::BrAnon(None)), - }; - let r = ty::Region::new_late_bound(fcx.tcx, current_depth, br); - r - }); - captured_tys.insert(ty).then(|| { - cause.ty = ty; - cause - }) - }) - .collect(); - - let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![]; - let mut counter = 0; - // Optimization: If there is only one captured type, then we don't actually - // need to fold and reindex (since the first type doesn't change). - let type_causes = if captured_tys.len() > 0 { - // Optimization: Use `replace_escaping_bound_vars_uncached` instead of - // `fold_regions`, since we only have late bound regions, and it skips - // types without bound regions. - fcx.tcx.replace_escaping_bound_vars_uncached( - type_causes, - FnMutDelegate { - regions: &mut |br| { - let kind = br.kind; - let var = ty::BoundVar::from_usize(bound_vars.len()); - bound_vars.push(ty::BoundVariableKind::Region(kind)); - counter += 1; - ty::Region::new_late_bound( - fcx.tcx, - ty::INNERMOST, - ty::BoundRegion { var, kind }, - ) - }, - types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"), - consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"), - }, - ) - } else { - type_causes - }; - - // 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 = - 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. - fcx.inh.typeck_results.borrow_mut().generator_interior_types = - ty::Binder::bind_with_vars(type_causes, bound_vars); - - debug!( - "types in generator after region replacement {:?}, span = {:?}", - witness, body.value.span - ); - - // Unify the type variable inside the generator with the new witness - match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq( - DefineOpaqueTypes::No, - interior, - witness, - ) { - Ok(ok) => fcx.register_infer_ok_obligations(ok), - _ => bug!("failed to relate {interior} and {witness}"), - } -} - -// This visitor has to have the same visit_expr calls as RegionResolutionVisitor in -// librustc_middle/middle/region.rs since `expr_count` is compared against the results -// there. -impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { - fn visit_arm(&mut self, arm: &'tcx Arm<'tcx>) { - let Arm { guard, pat, body, .. } = arm; - self.visit_pat(pat); - if let Some(ref g) = guard { - { - // If there is a guard, we need to count all variables bound in the pattern as - // borrowed for the entire guard body, regardless of whether they are accessed. - // We do this by walking the pattern bindings and recording `&T` for any `x: T` - // that is bound. - - struct ArmPatCollector<'a, 'b, 'tcx> { - interior_visitor: &'a mut InteriorVisitor<'b, 'tcx>, - scope: Scope, - } - - impl<'a, 'b, 'tcx> Visitor<'tcx> for ArmPatCollector<'a, 'b, 'tcx> { - fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { - intravisit::walk_pat(self, pat); - if let PatKind::Binding(_, id, ident, ..) = pat.kind { - let ty = - self.interior_visitor.fcx.typeck_results.borrow().node_type(id); - let tcx = self.interior_visitor.fcx.tcx; - let ty = Ty::new_ref( - tcx, - // Use `ReErased` as `resolve_interior` is going to replace all the - // regions anyway. - tcx.lifetimes.re_erased, - ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }, - ); - self.interior_visitor.record( - ty, - id, - Some(self.scope), - None, - ident.span, - ); - } - } - } - - ArmPatCollector { - interior_visitor: self, - scope: Scope { id: g.body().hir_id.local_id, data: ScopeData::Node }, - } - .visit_pat(pat); - } - - match g { - Guard::If(ref e) => { - self.visit_expr(e); - } - Guard::IfLet(ref l) => { - self.visit_let_expr(l); - } - } - } - self.visit_expr(body); - } - - fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { - intravisit::walk_pat(self, pat); - - self.expr_count += 1; - - if let PatKind::Binding(..) = pat.kind { - let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); - let ty = self.fcx.typeck_results.borrow().pat_ty(pat); - self.record(ty, pat.hir_id, Some(scope), None, pat.span); - } - } - - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - match &expr.kind { - ExprKind::Call(callee, args) => match &callee.kind { - ExprKind::Path(qpath) => { - let res = self.fcx.typeck_results.borrow().qpath_res(qpath, callee.hir_id); - match res { - // Direct calls never need to keep the callee `ty::FnDef` - // ZST in a temporary, so skip its type, just in case it - // can significantly complicate the generator type. - Res::Def( - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn), - _, - ) => { - // NOTE(eddyb) this assumes a path expression has - // no nested expressions to keep track of. - self.expr_count += 1; - - // Record the rest of the call expression normally. - for arg in *args { - self.visit_expr(arg); - } - } - _ => intravisit::walk_expr(self, expr), - } - } - _ => intravisit::walk_expr(self, expr), - }, - _ => intravisit::walk_expr(self, expr), - } - - self.expr_count += 1; - - debug!("is_borrowed_temporary: {:?}", self.drop_ranges.is_borrowed_temporary(expr)); - - let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr); - - // Typically, the value produced by an expression is consumed by its parent in some way, - // so we only have to check if the parent contains a yield (note that the parent may, for - // example, store the value into a local variable, but then we already consider local - // variables to be live across their scope). - // - // However, in the case of temporary values, we are going to store the value into a - // temporary on the stack that is live for the current temporary scope and then return a - // reference to it. That value may be live across the entire temporary scope. - // - // There's another subtlety: if the type has an observable drop, it must be dropped after - // the yield, even if it's not borrowed or referenced after the yield. Ideally this would - // *only* happen for types with observable drop, not all types which wrap them, but that - // doesn't match the behavior of MIR borrowck and causes ICEs. See the FIXME comment in - // tests/ui/generator/drop-tracking-parent-expression.rs. - let scope = if self.drop_ranges.is_borrowed_temporary(expr) - || ty.map_or(true, |ty| { - // Avoid ICEs in needs_drop. - let ty = self.fcx.resolve_vars_if_possible(ty); - let ty = self.fcx.tcx.erase_regions(ty); - if ty.has_infer() { - self.fcx - .tcx - .sess - .delay_span_bug(expr.span, format!("inference variables in {ty}")); - true - } else { - ty.needs_drop(self.fcx.tcx, self.fcx.param_env) - } - }) { - self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id) - } else { - let parent_expr = self - .fcx - .tcx - .hir() - .parent_iter(expr.hir_id) - .find(|(_, node)| matches!(node, hir::Node::Expr(_))) - .map(|(id, _)| id); - debug!("parent_expr: {:?}", parent_expr); - match parent_expr { - Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }), - None => { - self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id) - } - } - }; - - // If there are adjustments, then record the final type -- - // this is the actual value that is being produced. - if let Some(adjusted_ty) = ty { - self.record(adjusted_ty, expr.hir_id, scope, Some(expr), expr.span); - } - - // Also record the unadjusted type (which is the only type if - // there are no adjustments). The reason for this is that the - // unadjusted value is sometimes a "temporary" that would wind - // up in a MIR temporary. - // - // As an example, consider an expression like `vec![].push(x)`. - // Here, the `vec![]` would wind up MIR stored into a - // temporary variable `t` which we can borrow to invoke - // `>::push(&mut t, x)`. - // - // Note that an expression can have many adjustments, and we - // are just ignoring those intermediate types. This is because - // those intermediate values are always linearly "consumed" by - // the other adjustments, and hence would never be directly - // captured in the MIR. - // - // (Note that this partly relies on the fact that the `Deref` - // traits always return references, which means their content - // can be reborrowed without needing to spill to a temporary. - // If this were not the case, then we could conceivably have - // to create intermediate temporaries.) - // - // The type table might not have information for this expression - // if it is in a malformed scope. (#66387) - if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) { - self.record(ty, expr.hir_id, scope, Some(expr), expr.span); - } else { - self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); - } - } -} - -#[derive(Default)] -struct SuspendCheckData<'a, 'tcx> { - expr: Option<&'tcx Expr<'tcx>>, - source_span: Span, - yield_span: Span, - descr_pre: &'a str, - descr_post: &'a str, - plural_len: usize, -} - -// Returns whether it emitted a diagnostic or not -// Note that this fn and the proceeding one are based on the code -// for creating must_use diagnostics -// -// Note that this technique was chosen over things like a `Suspend` marker trait -// as it is simpler and has precedent in the compiler -fn check_must_not_suspend_ty<'tcx>( - fcx: &FnCtxt<'_, 'tcx>, - ty: Ty<'tcx>, - hir_id: HirId, - data: SuspendCheckData<'_, 'tcx>, -) -> bool { - if ty.is_unit() - // FIXME: should this check `Ty::is_inhabited_from`. This query is not available in this stage - // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in - // `must_use` - // || !ty.is_inhabited_from(fcx.tcx, fcx.tcx.parent_module(hir_id).to_def_id(), fcx.param_env) - { - return false; - } - - let plural_suffix = pluralize!(data.plural_len); - - debug!("Checking must_not_suspend for {}", ty); - - match *ty.kind() { - ty::Adt(..) if ty.is_box() => { - let boxed_ty = ty.boxed_ty(); - let descr_pre = &format!("{}boxed ", data.descr_pre); - check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data }) - } - ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data), - // FIXME: support adding the attribute to TAITs - ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - let mut has_emitted = false; - for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::ClauseKind::Trait(ref poly_trait_predicate) = - predicate.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); - if check_must_not_suspend_def( - fcx.tcx, - def_id, - hir_id, - SuspendCheckData { descr_pre, ..data }, - ) { - has_emitted = true; - break; - } - } - } - has_emitted - } - ty::Dynamic(binder, _, _) => { - let mut has_emitted = false; - for predicate in binder.iter() { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - let def_id = trait_ref.def_id; - let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post); - if check_must_not_suspend_def( - fcx.tcx, - def_id, - hir_id, - SuspendCheckData { descr_post, ..data }, - ) { - has_emitted = true; - break; - } - } - } - has_emitted - } - ty::Tuple(fields) => { - let mut has_emitted = false; - let comps = match data.expr.map(|e| &e.kind) { - Some(hir::ExprKind::Tup(comps)) if comps.len() == fields.len() => Some(comps), - _ => None, - }; - for (i, ty) in fields.iter().enumerate() { - let descr_post = &format!(" in tuple element {i}"); - let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span); - if check_must_not_suspend_ty( - fcx, - ty, - hir_id, - SuspendCheckData { - descr_post, - expr: comps.and_then(|comps| comps.get(i)), - source_span: span, - ..data - }, - ) { - has_emitted = true; - } - } - has_emitted - } - ty::Array(ty, len) => { - let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); - let target_usize = - len.try_eval_target_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize; - let plural_len = target_usize.saturating_add(1); - check_must_not_suspend_ty( - fcx, - ty, - hir_id, - SuspendCheckData { descr_pre, plural_len, ..data }, - ) - } - // If drop tracking is enabled, we want to look through references, since the referent - // may not be considered live across the await point. - ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => { - let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix); - check_must_not_suspend_ty(fcx, ty, hir_id, SuspendCheckData { descr_pre, ..data }) - } - _ => false, - } -} - -fn check_must_not_suspend_def( - tcx: TyCtxt<'_>, - def_id: DefId, - hir_id: HirId, - data: SuspendCheckData<'_, '_>, -) -> bool { - if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) { - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::MUST_NOT_SUSPEND, - hir_id, - data.source_span, - DelayDm(|| { - format!( - "{}`{}`{} held across a suspend point, but should not be", - data.descr_pre, - tcx.def_path_str(def_id), - data.descr_post, - ) - }), - |lint| { - // add span pointing to the offending yield/await - lint.span_label(data.yield_span, "the value is held across this suspend point"); - - // Add optional reason note - if let Some(note) = attr.value_str() { - // FIXME(guswynn): consider formatting this better - lint.span_note(data.source_span, note.to_string()); - } - - // Add some quick suggestions on what to do - // FIXME: can `drop` work as a suggestion here as well? - lint.span_help( - data.source_span, - "consider using a block (`{ ... }`) \ - to shrink the value's scope, ending before the suspend point", - ); - - lint - }, - ); - - true - } else { - false - } -} diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index f17f1d14bf390..cd6adb345e7a3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -5,7 +5,6 @@ #![feature(box_patterns)] #![feature(min_specialization)] #![feature(control_flow_enum)] -#![feature(option_as_slice)] #![recursion_limit = "256"] #[macro_use] @@ -32,7 +31,6 @@ pub mod expr_use_visitor; mod fallback; mod fn_ctxt; mod gather_locals; -mod generator_interior; mod inherited; mod intrinsicck; mod mem_categorization; diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 7fb1dc2347e05..337d12b2d5111 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // Opaque types can't have field projections, but we can instead convert // the current place in-place (heh) to the hidden type, and then apply all // follow up projections on that. - if node_ty != place_ty && place_ty.has_opaque_types() { + if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) { projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); } projections.push(Projection { kind, ty }); @@ -557,10 +557,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id)) } Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _) - | Res::Def( - DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy, - _, - ) + | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfCtor(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 07c48ec6392a8..a4bbb16026a73 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2494,10 +2494,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not // just this list. - for (rcvr_ty, post) in &[ - (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), "&"), + for (rcvr_ty, post, pin_call) in &[ + (rcvr_ty, "", None), + ( + Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), + "&mut ", + Some("as_mut"), + ), + ( + Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), + "&", + Some("as_ref"), + ), ] { match self.lookup_probe_for_diagnostic( item_name, @@ -2531,6 +2539,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(_) => (), } + let pred = ty::TraitRef::new( + self.tcx, + self.tcx.lang_items().unpin_trait().unwrap(), + [*rcvr_ty], + ); + let unpin = self.predicate_must_hold_considering_regions(&Obligation::new( + self.tcx, + ObligationCause::misc(rcvr.span, self.body_id), + self.param_env, + pred, + )); for (rcvr_ty, pre) in &[ (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"), (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"), @@ -2554,7 +2573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not // implement the `AsRef` trait. let skip = skippable.contains(&did) - || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)) + || (("Pin::new" == *pre) && ((sym::as_ref == item_name.name) || !unpin)) || inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len); // Make sure the method is defined for the *actual* receiver: we don't // want to treat `Box` as a receiver if it only works because of @@ -2566,7 +2585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.multipart_suggestion( "consider wrapping the receiver expression with the \ - appropriate type", + appropriate type", vec![ (rcvr.span.shrink_to_lo(), format!("{pre}({post}")), (rcvr.span.shrink_to_hi(), ")".to_string()), @@ -2578,6 +2597,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + // We special case the situation where `Pin::new` wouldn't work, and instead + // suggest using the `pin!()` macro instead. + if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin) + // We didn't find an alternative receiver for the method. + && !alt_rcvr_sugg + // `T: !Unpin` + && !unpin + // The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`. + && sym::as_ref != item_name.name + // Either `Pin::as_ref` or `Pin::as_mut`. + && let Some(pin_call) = pin_call + // Search for `item_name` as a method accessible on `Pin`. + && let Ok(pick) = self.lookup_probe_for_diagnostic( + item_name, + new_rcvr_t, + rcvr, + ProbeScope::AllTraits, + return_type, + ) + // We skip some common traits that we don't want to consider because autoderefs + // would take care of them. + && !skippable.contains(&Some(pick.item.container_id(self.tcx))) + // We don't want to go through derefs. + && pick.autoderefs == 0 + // Check that the method of the same name that was found on the new `Pin` + // receiver has the same number of arguments that appear in the user's code. + && inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len) + { + let indent = self.tcx.sess + .source_map() + .indentation_before(rcvr.span) + .unwrap_or_else(|| " ".to_string()); + err.multipart_suggestion( + "consider pinning the expression", + vec![ + (rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")), + (rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")), + ], + Applicability::MaybeIncorrect, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; + } } } if self.suggest_valid_traits(err, valid_out_of_scope_traits) { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8fc236f46b226..3f9c9b3381baa 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -12,7 +12,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::edit_distance::find_best_match_for_name; @@ -1408,6 +1407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, + pat, variant, args, )) @@ -1434,15 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields .iter() .copied() - .filter(|(field, _)| { - field.vis.is_accessible_from(tcx.parent_module(pat.hir_id), tcx) - && !matches!( - tcx.eval_stability(field.did, None, DUMMY_SP, None), - EvalResult::Deny { .. } - ) - // We only want to report the error if it is hidden and not local - && !(tcx.is_doc_hidden(field.did) && !field.did.is_local()) - }) + .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span)) .collect(); if !has_rest_pat { @@ -1578,12 +1570,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind_name: &str, inexistent_fields: &[&hir::PatField<'tcx>], unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>, + pat: &'tcx Pat<'tcx>, variant: &ty::VariantDef, args: &'tcx ty::List>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let tcx = self.tcx; - let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0].ident), "this", "") + let (field_names, t, plural) = if let [field] = inexistent_fields { + (format!("a field named `{}`", field.ident), "this", "") } else { ( format!( @@ -1620,10 +1613,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); - if unmentioned_fields.len() == 1 { - let input = - unmentioned_fields.iter().map(|(_, field)| field.name).collect::>(); - let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None); + if let [(field_def, field)] = unmentioned_fields.as_slice() + && self.is_field_suggestable(field_def, pat.hir_id, pat.span) + { + let suggested_name = + find_best_match_for_name(&[field.name], pat_field.ident.name, None); if let Some(suggested_name) = suggested_name { err.span_suggestion( pat_field.ident.span, @@ -1646,22 +1640,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Lit(expr) if !self.can_coerce( self.typeck_results.borrow().expr_ty(expr), - self.field_ty( - unmentioned_fields[0].1.span, - unmentioned_fields[0].0, - args, - ), + self.field_ty(field.span, field_def, args), ) => {} _ => { - let unmentioned_field = unmentioned_fields[0].1.name; err.span_suggestion_short( pat_field.ident.span, format!( "`{}` has a field named `{}`", tcx.def_path_str(variant.def_id), - unmentioned_field + field.name, ), - unmentioned_field.to_string(), + field.name, Applicability::MaybeIncorrect, ); } @@ -1871,8 +1860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; - let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`{}", unmentioned_fields[0].1, inaccessible) + let field_names = if let [(_, field)] = unmentioned_fields { + format!("field `{field}`{inaccessible}") } else { let fields = unmentioned_fields .iter() diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index ba469bd029d4d..4d64139036811 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -41,6 +41,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{ self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture, }; @@ -295,6 +296,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let final_upvar_tys = self.final_upvar_tys(closure_def_id); debug!(?closure_hir_id, ?args, ?final_upvar_tys); + if self.tcx.features().unsized_locals || self.tcx.features().unsized_fn_params { + for capture in + self.typeck_results.borrow().closure_min_captures_flattened(closure_def_id) + { + if let UpvarCapture::ByValue = capture.info.capture_kind { + self.require_type_is_sized( + capture.place.ty(), + capture.get_path_span(self.tcx), + ObligationCauseCode::SizedClosureCapture(closure_def_id), + ); + } + } + } + // 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 = Ty::new_tup(self.tcx, &final_upvar_tys); diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 603681bbc994a..9c16b486dbc97 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Type only exists for constants and statics, not functions. match self.tcx.hir().body_owner_kind(item_def_id) { - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => { + hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => { let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id); wbcx.visit_node_id(body.value.span, item_hir_id); } @@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_coercion_casts(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); - wbcx.visit_generator_interior_types(); + wbcx.visit_generator_interior(); wbcx.visit_offset_of_container_types(); wbcx.typeck_results.rvalue_scopes = @@ -538,11 +538,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ); } - fn visit_generator_interior_types(&mut self) { + fn visit_generator_interior(&mut self) { let fcx_typeck_results = self.fcx.typeck_results.borrow(); assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner); - self.typeck_results.generator_interior_types = - fcx_typeck_results.generator_interior_types.clone(); self.tcx().with_stable_hashing_context(move |ref hcx| { for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.to_sorted(hcx, false).into_iter() diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 5e7ae3ecdb85d..1b160eca92db7 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -42,7 +42,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{ - DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, + dep_kinds, DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; @@ -129,7 +129,7 @@ impl<'tcx> IfThisChanged<'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { None => { - DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) + DepNode::from_def_path_hash(self.tcx, def_path_hash, dep_kinds::hir_owner) } Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index b9171fad55ba3..220ea194a6de1 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -28,8 +28,8 @@ pub use persist::load_query_result_cache; pub use persist::prepare_session_directory; pub use persist::save_dep_graph; pub use persist::save_work_product_index; +pub use persist::setup_dep_graph; pub use persist::LoadResult; -pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture}; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 8d67f69256879..2310d0b12ef0c 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -3,17 +3,19 @@ use crate::errors; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::unord::UnordMap; -use rustc_middle::dep_graph::{SerializedDepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; -use rustc_session::Session; +use rustc_session::{Session, StableCrateId}; +use rustc_span::{ErrorGuaranteed, Symbol}; use std::path::{Path, PathBuf}; use super::data::*; use super::file_format; use super::fs::*; +use super::save::build_dep_graph; use super::work_product; #[derive(Debug)] @@ -72,21 +74,12 @@ impl LoadResult { } fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> { - load_data_no_sess( + match file_format::read_file( path, sess.opts.unstable_opts.incremental_info, sess.is_nightly_build(), sess.cfg_version, - ) -} - -fn load_data_no_sess( - path: &Path, - report_incremental_info: bool, - is_nightly_build: bool, - cfg_version: &'static str, -) -> LoadResult<(Mmap, usize)> { - match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) { + ) { Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos }, Ok(None) => { // The file either didn't exist or was produced by an incompatible @@ -102,39 +95,12 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) { work_product::delete_workproduct_files(sess, &swp.work_product); } -/// Either a result that has already be computed or a -/// handle that will let us wait until it is computed -/// by a background thread. -pub enum MaybeAsync { - Sync(T), - Async(std::thread::JoinHandle), -} - -impl MaybeAsync> { - /// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible. - pub fn open(self) -> LoadResult { - match self { - MaybeAsync::Sync(result) => result, - MaybeAsync::Async(handle) => { - handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e)) - } - } - } -} - -/// An asynchronous type for computing the dependency graph. -pub type DepGraphFuture = MaybeAsync>; - -/// Launch a thread and load the dependency graph in the background. -pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { - // Since `sess` isn't `Sync`, we perform all accesses to `sess` - // before we fire the background thread. - +fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProductMap)> { let prof = sess.prof.clone(); if sess.opts.incremental.is_none() { // No incremental compilation. - return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() }); + return LoadResult::Ok { data: Default::default() }; } let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph"); @@ -142,7 +108,6 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. let path = dep_graph_path(&sess); - let report_incremental_info = sess.opts.unstable_opts.incremental_info; let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); @@ -180,40 +145,35 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { } } - let is_nightly_build = sess.is_nightly_build(); - let cfg_version = sess.cfg_version; - - MaybeAsync::Async(std::thread::spawn(move || { - let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph"); + let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph"); - match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) { - LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, - LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), - LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), - LoadResult::Ok { data: (bytes, start_pos) } => { - let mut decoder = MemDecoder::new(&bytes, start_pos); - let prev_commandline_args_hash = u64::decode(&mut decoder); + match load_data(&path, sess) { + LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), + LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), + LoadResult::Ok { data: (bytes, start_pos) } => { + let mut decoder = MemDecoder::new(&bytes, start_pos); + let prev_commandline_args_hash = u64::decode(&mut decoder); - if prev_commandline_args_hash != expected_hash { - if report_incremental_info { - eprintln!( - "[incremental] completely ignoring cache because of \ + if prev_commandline_args_hash != expected_hash { + if sess.opts.unstable_opts.incremental_info { + eprintln!( + "[incremental] completely ignoring cache because of \ differing commandline arguments" - ); - } - // We can't reuse the cache, purge it. - debug!("load_dep_graph_new: differing commandline arg hashes"); - - // No need to do any further work - return LoadResult::DataOutOfDate; + ); } + // We can't reuse the cache, purge it. + debug!("load_dep_graph_new: differing commandline arg hashes"); - let dep_graph = SerializedDepGraph::decode(&mut decoder); - - LoadResult::Ok { data: (dep_graph, prev_work_products) } + // No need to do any further work + return LoadResult::DataOutOfDate; } + + let dep_graph = SerializedDepGraph::decode::(&mut decoder); + + LoadResult::Ok { data: (dep_graph, prev_work_products) } } - })) + } } /// Attempts to load the query result cache from disk @@ -235,3 +195,35 @@ pub fn load_query_result_cache(sess: &Session) -> Option> { _ => Some(OnDiskCache::new_empty(sess.source_map())), } } + +/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a +/// new graph to an incremental session directory. +pub fn setup_dep_graph( + sess: &Session, + crate_name: Symbol, + stable_crate_id: StableCrateId, +) -> Result { + // `load_dep_graph` can only be called after `prepare_session_directory`. + prepare_session_directory(sess, crate_name, stable_crate_id)?; + + let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess)); + + if sess.opts.incremental.is_some() { + sess.time("incr_comp_garbage_collect_session_directories", || { + if let Err(e) = garbage_collect_session_directories(sess) { + warn!( + "Error while trying to garbage collect incremental \ + compilation cache directory: {}", + e + ); + } + }); + } + + Ok(res + .and_then(|result| { + let (prev_graph, prev_work_products) = result.open(sess); + build_dep_graph(sess, prev_graph, prev_work_products) + }) + .unwrap_or_else(DepGraph::new_disabled)) +} diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index 1336189bc0d26..fdecaca5a2dc1 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -16,9 +16,8 @@ pub use fs::in_incr_comp_dir; pub use fs::in_incr_comp_dir_sess; pub use fs::prepare_session_directory; pub use load::load_query_result_cache; +pub use load::setup_dep_graph; pub use load::LoadResult; -pub use load::{load_dep_graph, DepGraphFuture}; -pub use save::build_dep_graph; pub use save::save_dep_graph; pub use save::save_work_product_index; pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 7719482890e6e..210da751d95e4 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -147,7 +147,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult /// execution, the new dependency information is not kept in memory but directly /// output to this file. `save_dep_graph` then finalizes the staging dep-graph /// and moves it to the permanent dep-graph path -pub fn build_dep_graph( +pub(crate) fn build_dep_graph( sess: &Session, prev_graph: SerializedDepGraph, prev_work_products: WorkProductMap, diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 12a7ecf813374..ece61ff12520c 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -365,7 +365,7 @@ impl From> for BitSet { /// All operations that involve an element will panic if the element is equal /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. -#[derive(Debug, PartialEq, Eq)] +#[derive(PartialEq, Eq)] pub struct ChunkedBitSet { domain_size: usize, @@ -1074,6 +1074,12 @@ impl fmt::Debug for BitSet { } } +impl fmt::Debug for ChunkedBitSet { + fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { + w.debug_list().entries(self.iter()).finish() + } +} + impl ToString for BitSet { fn to_string(&self) -> String { let mut result = String::new(); diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 4d0e770636721..b36fb6a4dbac9 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -66,7 +66,6 @@ infer_await_both_futures = consider `await`ing on both `Future`s infer_await_future = consider `await`ing on the `Future` infer_await_note = calling an async function returns a future -infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long infer_but_calling_introduces = {$has_param_name -> [true] `{$param_name}` *[false] `fn` parameter @@ -181,8 +180,6 @@ infer_more_targeted = {$has_param_name -> } but calling `{$ident}` introduces an implicit `'static` lifetime requirement infer_msl_introduces_static = introduces a `'static` lifetime requirement -infer_msl_trait_note = this has an implicit `'static` lifetime requirement -infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement infer_msl_unmet_req = because this has an unmet lifetime requirement infer_need_type_info_in_generator = type inside {$generator_kind -> @@ -198,6 +195,10 @@ infer_nothing = {""} infer_oc_cant_coerce = cannot coerce intrinsics to function pointers infer_oc_closure_selfref = closure/generator type that references itself infer_oc_const_compat = const not compatible with trait +infer_oc_fn_lang_correct_type = {$lang_item_name -> + [panic_impl] `#[panic_handler]` + *[lang_item_name] lang item `{$lang_item_name}` + } function has wrong type infer_oc_fn_main_correct_type = `main` function has wrong type infer_oc_fn_start_correct_type = `#[start]` function has wrong type infer_oc_generic = mismatched types @@ -229,7 +230,6 @@ infer_prlf_known_limitation = this is a known limitation that will be removed in infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here infer_reborrow = ...so that reference does not outlive borrowed content -infer_reborrow_upvar = ...so that closure can access `{$name}` infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at @@ -337,6 +337,7 @@ infer_subtype = ...so that the {$requirement -> [no_else] `if` missing an `else` returns `()` [fn_main_correct_type] `main` function has the correct type [fn_start_correct_type] `#[start]` function has the correct type + [fn_lang_correct_type] lang item function has the correct type [intrinsic_correct_type] intrinsic has the correct type [method_correct_type] method receiver has the correct type *[other] types are compatible @@ -350,6 +351,7 @@ infer_subtype_2 = ...so that {$requirement -> [no_else] `if` missing an `else` returns `()` [fn_main_correct_type] `main` function has the correct type [fn_start_correct_type] `#[start]` function has the correct type + [fn_lang_correct_type] lang item function has the correct type [intrinsic_correct_type] intrinsic has the correct type [method_correct_type] method receiver has the correct type *[other] types are compatible diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index a7e045e1e8946..3ff1a5c0c14b0 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -14,8 +14,7 @@ use rustc_span::{symbol::Ident, BytePos, Span}; use crate::fluent_generated as fluent; use crate::infer::error_reporting::{ - need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, - nice_region_error::placeholder_error::Highlighted, + need_type_info::UnderspecifiedArgKind, nice_region_error::placeholder_error::Highlighted, ObligationCauseAsDiagArg, }; @@ -86,16 +85,6 @@ pub struct AmbiguousReturn<'a> { pub multi_suggestions: Vec>, } -#[derive(Diagnostic)] -#[diag(infer_need_type_info_in_generator, code = "E0698")] -pub struct NeedTypeInfoInGenerator<'a> { - #[primary_span] - pub span: Span, - pub generator_kind: GeneratorKindAsDiagArg, - #[subdiagnostic] - pub bad_label: InferenceBadError<'a>, -} - // Used when a better one isn't available #[derive(Subdiagnostic)] #[label(infer_label_bad)] @@ -205,13 +194,13 @@ impl<'a> SourceKindMultiSuggestion<'a> { data: &'a FnRetTy<'a>, should_wrap_expr: Option, ) -> Self { - let (arrow, post) = match data { - FnRetTy::DefaultReturn(_) => ("-> ", " "), - _ => ("", ""), + let arrow = match data { + FnRetTy::DefaultReturn(_) => " -> ", + _ => "", }; let (start_span, start_span_code, end_span) = match should_wrap_expr { - Some(end_span) => (data.span(), format!("{arrow}{ty_info}{post}{{ "), Some(end_span)), - None => (data.span(), format!("{arrow}{ty_info}{post}"), None), + Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)), + None => (data.span(), format!("{arrow}{ty_info}"), None), }; Self::ClosureReturn { start_span, start_span_code, end_span } } @@ -1463,6 +1452,14 @@ pub enum ObligationCauseFailureCode { #[subdiagnostic] subdiags: Vec, }, + #[diag(infer_oc_fn_lang_correct_type, code = "E0308")] + FnLangCorrectType { + #[primary_span] + span: Span, + #[subdiagnostic] + subdiags: Vec, + lang_item_name: Symbol, + }, #[diag(infer_oc_intrinsic_correct_type, code = "E0308")] IntrinsicCorrectType { #[primary_span] diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index bd168f047faf5..9276bb0a7b7c1 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -56,11 +56,8 @@ impl<'a> DescriptionCtx<'a> { (Some(span), "as_defined", name.to_string()) } } - ty::BrAnon(span) => { - let span = match span { - Some(_) => span, - None => Some(tcx.def_span(scope)), - }; + ty::BrAnon => { + let span = Some(tcx.def_span(scope)); (span, "defined_here", String::new()) } _ => { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 6d5db3336cfbf..2797d07976113 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -478,7 +478,28 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { a: Self, b: Self, ) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) } + TypeTrace { + cause: cause.clone(), + values: PolySigs(ExpectedFound::new( + a_is_expected, + ty::Binder::dummy(a), + ty::Binder::dummy(b), + )), + } + } +} + +impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> { + fn to_trace( + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self, + ) -> TypeTrace<'tcx> { + TypeTrace { + cause: cause.clone(), + values: PolySigs(ExpectedFound::new(a_is_expected, a, b)), + } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 99bd296d0d5e0..4124c9eada9c1 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -459,7 +459,6 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Bool | ty::Char | ty::Int(..) @@ -776,7 +775,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { var, kind: ty::BrAnon(None) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon }; ty::Region::new_late_bound(self.interner(), self.binder_index, br) } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 1dbab48fd6ceb..665297da20f89 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -119,26 +119,6 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { .obligations, ); } - // Optimization of GeneratorWitness relation since we know that all - // free regions are replaced with bound regions during construction. - // This greatly speeds up equating of GeneratorWitness. - (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { - let a_types = infcx.tcx.anonymize_bound_vars(a_types); - let b_types = infcx.tcx.anonymize_bound_vars(b_types); - if a_types.bound_vars() == b_types.bound_vars() { - let (a_types, b_types) = infcx.instantiate_binder_with_placeholders( - a_types.map_bound(|a_types| (a_types, b_types.skip_binder())), - ); - for (a, b) in std::iter::zip(a_types, b_types) { - self.relate(a, b)?; - } - } else { - return Err(ty::error::TypeError::Sorts(ty::relate::expected_found( - self, a, b, - ))); - } - } - _ => { self.fields.infcx.super_combine_tys(self, a, b)?; } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6dba5d2945dbe..12dcb7118203a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -59,20 +59,19 @@ use crate::traits::{ }; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_errors::{error_code, Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::Node; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ - self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, + self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; @@ -242,12 +241,9 @@ fn msg_span_from_named_region<'tcx>( }; (text, Some(span)) } - ty::BrAnon(span) => ( + ty::BrAnon => ( "the anonymous lifetime as defined here".to_string(), - Some(match span { - Some(span) => span, - None => tcx.def_span(scope) - }) + Some(tcx.def_span(scope)) ), _ => ( format!("the lifetime `{region}` as defined here"), @@ -262,11 +258,7 @@ fn msg_span_from_named_region<'tcx>( .. }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))), ty::RePlaceholder(ty::PlaceholderRegion { - bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. }, - .. - }) => ("the anonymous lifetime defined here".to_owned(), Some(span)), - ty::RePlaceholder(ty::PlaceholderRegion { - bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. }, + bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon, .. }, .. }) => ("an anonymous lifetime".to_owned(), None), _ => bug!("{:?}", region), @@ -1616,7 +1608,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // | expected `()`, found closure // | // = note: expected unit type `()` - // found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]` + // found closure `{closure@$DIR/issue-20862.rs:2:5: 2:14 x:_}` // // Also ignore opaque `Future`s that come from async fns. if !self.ignore_span.overlaps(span) @@ -1660,7 +1652,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _ => (false, Mismatch::Fixed("type")), } } - ValuePairs::Sigs(infer::ExpectedFound { expected, found }) => { + ValuePairs::PolySigs(infer::ExpectedFound { expected, found }) => { OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span) .report(diag); (false, Mismatch::Fixed("signature")) @@ -2232,15 +2224,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ret => ret, } } - infer::Sigs(exp_found) => { + infer::PolySigs(exp_found) => { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; } - let (exp, fnd) = self.cmp_fn_sig( - &ty::Binder::dummy(exp_found.expected), - &ty::Binder::dummy(exp_found.found), - ); + let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found); Some((exp, fnd, None, None)) } } @@ -2327,113 +2316,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - // Attempt to obtain the span of the parameter so we can - // suggest adding an explicit lifetime bound to it. - let generics = self.tcx.generics_of(generic_param_scope); - // type_param_span is (span, has_bounds) - let mut is_synthetic = false; - let mut ast_generics = None; - let type_param_span = match bound_kind { - GenericKind::Param(ref param) => { - // Account for the case where `param` corresponds to `Self`, - // which doesn't have the expected type argument. - if !(generics.has_self && param.index == 0) { - let type_param = generics.type_param(param, self.tcx); - is_synthetic = type_param.kind.is_synthetic(); - type_param.def_id.as_local().map(|def_id| { - // Get the `hir::Param` to verify whether it already has any bounds. - // We do this to avoid suggesting code that ends up as `T: 'a'b`, - // instead we suggest `T: 'a + 'b` in that case. - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id); - let bounds = - ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id)); - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - if let Some(span) = bounds { - (span, true) - } else { - let sp = self.tcx.def_span(def_id); - (sp.shrink_to_hi(), false) - } - }) - } else { - None - } - } - _ => None, - }; - - let new_lt = { - let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char)); - let lts_names = - iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p))) - .flat_map(|g| &g.params) - .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) - .map(|p| p.name.as_str()) - .collect::>(); - possible - .find(|candidate| !lts_names.contains(&&candidate[..])) - .unwrap_or("'lt".to_string()) - }; - - let mut add_lt_suggs: Vec> = vec![]; - if is_synthetic { - if let Some(ast_generics) = ast_generics { - let named_lifetime_param_exist = ast_generics.params.iter().any(|p| { - matches!( - p.kind, - hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } - ) - }); - if named_lifetime_param_exist && let [param, ..] = ast_generics.params - { - add_lt_suggs.push(Some(( - self.tcx.def_span(param.def_id).shrink_to_lo(), - format!("{new_lt}, "), - ))); - } else { - add_lt_suggs - .push(Some((ast_generics.span.shrink_to_hi(), format!("<{new_lt}>")))); - } - } - } else { - if let [param, ..] = &generics.params[..] && let Some(def_id) = param.def_id.as_local() - { - add_lt_suggs - .push(Some((self.tcx.def_span(def_id).shrink_to_lo(), format!("{new_lt}, ")))); - } - } - - if let Some(ast_generics) = ast_generics { - for p in ast_generics.params { - if p.is_elided_lifetime() { - if self - .tcx - .sess - .source_map() - .span_to_prev_source(p.span.shrink_to_hi()) - .ok() - .is_some_and(|s| *s.as_bytes().last().unwrap() == b'&') - { - add_lt_suggs - .push(Some( - ( - p.span.shrink_to_hi(), - if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span) - && snip.starts_with(' ') - { - new_lt.to_string() - } else { - format!("{new_lt} ") - } - ) - )); - } else { - add_lt_suggs.push(Some((p.span.shrink_to_hi(), format!("<{new_lt}>")))); - } - } - } + if let Some(SubregionOrigin::CompareImplItemObligation { + span, + impl_item_def_id, + trait_item_def_id, + }) = origin + { + return self.report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{bound_kind}: {sub}`"), + ); } let labeled_user_string = match bound_kind { @@ -2447,223 +2341,207 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }, }; - if let Some(SubregionOrigin::CompareImplItemObligation { + let mut err = self.tcx.sess.struct_span_err_with_code( span, - impl_item_def_id, - trait_item_def_id, - }) = origin - { - return self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{bound_kind}: {sub}`"), - ); + format!("{labeled_user_string} may not live long enough"), + match sub.kind() { + ty::ReEarlyBound(_) | ty::ReFree(_) if sub.has_name() => error_code!(E0309), + ty::ReStatic => error_code!(E0310), + _ => error_code!(E0311), + }, + ); + + '_explain: { + let (description, span) = match sub.kind() { + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { + msg_span_from_named_region(self.tcx, sub, Some(span)) + } + _ => (format!("lifetime `{sub}`"), Some(span)), + }; + let prefix = format!("{labeled_user_string} must be valid for "); + label_msg_span(&mut err, &prefix, description, span, "..."); + if let Some(origin) = origin { + self.note_region_origin(&mut err, &origin); + } } - fn binding_suggestion<'tcx, S: fmt::Display>( - err: &mut Diagnostic, - type_param_span: Option<(Span, bool)>, - bound_kind: GenericKind<'tcx>, - sub: S, - add_lt_suggs: Vec>, - ) { + 'suggestion: { let msg = "consider adding an explicit lifetime bound"; - if let Some((sp, has_lifetimes)) = type_param_span { - let suggestion = - if has_lifetimes { format!(" + {sub}") } else { format!(": {sub}") }; - let mut suggestions = vec![(sp, suggestion)]; - for add_lt_sugg in add_lt_suggs.into_iter().flatten() { - suggestions.push(add_lt_sugg); + + if (bound_kind, sub).has_infer_regions() + || (bound_kind, sub).has_placeholders() + || !bound_kind.is_suggestable(self.tcx, false) + { + let lt_name = sub.get_name_or_anon().to_string(); + err.help(format!("{msg} `{bound_kind}: {lt_name}`...")); + break 'suggestion; + } + + let mut generic_param_scope = generic_param_scope; + while self.tcx.def_kind(generic_param_scope) == DefKind::OpaqueTy { + generic_param_scope = self.tcx.local_parent(generic_param_scope); + } + + // type_param_sugg_span is (span, has_bounds) + let (type_scope, type_param_sugg_span) = match bound_kind { + GenericKind::Param(ref param) => { + let generics = self.tcx.generics_of(generic_param_scope); + let def_id = generics.type_param(param, self.tcx).def_id.expect_local(); + let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id; + // Get the `hir::Param` to verify whether it already has any bounds. + // We do this to avoid suggesting code that ends up as `T: 'a'b`, + // instead we suggest `T: 'a + 'b` in that case. + let hir_generics = self.tcx.hir().get_generics(scope).unwrap(); + let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) { + Some(span) => Some((span, true)), + // If `param` corresponds to `Self`, no usable suggestion span. + None if generics.has_self && param.index == 0 => None, + None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false)), + }; + (scope, sugg_span) } - err.multipart_suggestion_verbose( - format!("{msg}..."), - suggestions, - Applicability::MaybeIncorrect, // Issue #41966 - ); - } else { - let consider = format!("{msg} `{bound_kind}: {sub}`..."); - err.help(consider); - } - } - - let new_binding_suggestion = - |err: &mut Diagnostic, type_param_span: Option<(Span, bool)>| { - let msg = "consider introducing an explicit lifetime bound"; - if let Some((sp, has_lifetimes)) = type_param_span { - let suggestion = - if has_lifetimes { format!(" + {new_lt}") } else { format!(": {new_lt}") }; - let mut sugg = - vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {new_lt}"))]; - for lt in add_lt_suggs.clone().into_iter().flatten() { - sugg.push(lt); - sugg.rotate_right(1); - } - // `MaybeIncorrect` due to issue #41966. - err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect); + _ => (generic_param_scope, None), + }; + let suggestion_scope = { + let lifetime_scope = match sub.kind() { + ty::ReStatic => hir::def_id::CRATE_DEF_ID, + _ => match self.tcx.is_suitable_region(sub) { + Some(info) => info.def_id, + None => generic_param_scope, + }, + }; + match self.tcx.is_descendant_of(type_scope.into(), lifetime_scope.into()) { + true => type_scope, + false => lifetime_scope, } }; - #[derive(Debug)] - enum SubOrigin<'hir> { - GAT(&'hir hir::Generics<'hir>), - Impl, - Trait, - Fn, - Unknown, - } - let sub_origin = 'origin: { - match *sub { - ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => { - let node = self.tcx.hir().get_if_local(def_id).unwrap(); - match node { - Node::GenericParam(param) => { - for h in self.tcx.hir().parent_iter(param.hir_id) { - break 'origin match h.1 { - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(..), - generics, - .. - }) - | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Type(..), - generics, - .. - }) => SubOrigin::GAT(generics), - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(..), - .. - }) - | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(..), - .. - }) - | Node::Item(hir::Item { - kind: hir::ItemKind::Fn(..), .. - }) => SubOrigin::Fn, - Node::Item(hir::Item { - kind: hir::ItemKind::Trait(..), - .. - }) => SubOrigin::Trait, - Node::Item(hir::Item { - kind: hir::ItemKind::Impl(..), .. - }) => SubOrigin::Impl, - _ => continue, - }; - } + let mut suggs = vec![]; + let lt_name = self.suggest_name_region(sub, &mut suggs); + + if let Some((sp, has_lifetimes)) = type_param_sugg_span + && suggestion_scope == type_scope + { + let suggestion = + if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") }; + suggs.push((sp, suggestion)) + } else { + let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap(); + let pred = format!("{bound_kind}: {lt_name}"); + let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,); + suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion)) + } + + err.multipart_suggestion_verbose( + format!("{msg}"), + suggs, + Applicability::MaybeIncorrect, // Issue #41966 + ); + } + + err + } + + pub fn suggest_name_region( + &self, + lifetime: Region<'tcx>, + add_lt_suggs: &mut Vec<(Span, String)>, + ) -> String { + struct LifetimeReplaceVisitor<'tcx, 'a> { + tcx: TyCtxt<'tcx>, + needle: hir::LifetimeName, + new_lt: &'a str, + add_lt_suggs: &'a mut Vec<(Span, String)>, + } + + impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> { + fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) { + if lt.res == self.needle { + let (pos, span) = lt.suggestion_position(); + let new_lt = &self.new_lt; + let sugg = match pos { + hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"), + hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "), + hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"), + hir::LifetimeSuggestionPosition::ElidedPathArgument => { + format!("{new_lt}, ") } - _ => {} + hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"), + }; + self.add_lt_suggs.push((span, sugg)); + } + } + + fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) { + let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind else { + return hir::intravisit::walk_ty(self, ty); + }; + let opaque_ty = self.tcx.hir().item(item_id).expect_opaque_ty(); + if let Some(&(_, b)) = + opaque_ty.lifetime_mapping.iter().find(|&(a, _)| a.res == self.needle) + { + let prev_needle = + std::mem::replace(&mut self.needle, hir::LifetimeName::Param(b)); + for bound in opaque_ty.bounds { + self.visit_param_bound(bound); } + self.needle = prev_needle; } - _ => {} } - SubOrigin::Unknown - }; - debug!(?sub_origin); - - let mut err = match (*sub, sub_origin) { - // In the case of GATs, we have to be careful. If we a type parameter `T` on an impl, - // but a lifetime `'a` on an associated type, then we might need to suggest adding - // `where T: 'a`. Importantly, this is on the GAT span, not on the `T` declaration. - (ty::ReEarlyBound(ty::EarlyBoundRegion { name: _, .. }), SubOrigin::GAT(generics)) => { - // Does the required lifetime have a nice name we can print? - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0309, - "{} may not live long enough", - labeled_user_string - ); - let pred = format!("{bound_kind}: {sub}"); - let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,); - err.span_suggestion( - generics.tail_span_for_predicate_suggestion(), - "consider adding a where clause", - suggestion, - Applicability::MaybeIncorrect, - ); - err - } - ( - ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }), - _, - ) if name != kw::UnderscoreLifetime => { - // Does the required lifetime have a nice name we can print? - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0309, - "{} may not live long enough", - labeled_user_string - ); - // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl - // for the bound is not suitable for suggestions when `-Zverbose` is set because it - // uses `Debug` output, so we handle it specially here so that suggestions are - // always correct. - binding_suggestion(&mut err, type_param_span, bound_kind, name, vec![]); - err - } - - (ty::ReStatic, _) => { - // Does the required lifetime have a nice name we can print? - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0310, - "{} may not live long enough", - labeled_user_string - ); - binding_suggestion(&mut err, type_param_span, bound_kind, "'static", vec![]); - err + } + + let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) { + Some(info) if !lifetime.has_name() => { + (info.boundregion.get_id().unwrap().expect_local(), info.def_id) } + _ => return lifetime.get_name_or_anon().to_string(), + }; - _ => { - // If not, be less specific. - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0311, - "{} may not live long enough", - labeled_user_string - ); - note_and_explain_region( - self.tcx, - &mut err, - &format!("{labeled_user_string} must be valid for "), - sub, - "...", - None, - ); - if let Some(infer::RelateParamBound(_, t, _)) = origin { - let t = self.resolve_vars_if_possible(t); - match t.kind() { - // We've got: - // fn get_later(g: G, dest: &mut T) -> impl FnOnce() + '_ - // suggest: - // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - ty::Closure(..) | ty::Alias(ty::Opaque, ..) => { - new_binding_suggestion(&mut err, type_param_span); - } - _ => { - binding_suggestion( - &mut err, - type_param_span, - bound_kind, - new_lt, - add_lt_suggs, - ); - } + let new_lt = { + let generics = self.tcx.generics_of(lifetime_scope); + let mut used_names = + iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p))) + .flat_map(|g| &g.params) + .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) + .map(|p| p.name) + .collect::>(); + if let Some(hir_id) = self.tcx.opt_local_def_id_to_hir_id(lifetime_scope) { + // consider late-bound lifetimes ... + used_names.extend(self.tcx.late_bound_vars(hir_id).into_iter().filter_map(|p| { + match p { + ty::BoundVariableKind::Region(lt) => lt.get_name(), + _ => None, } - } - err + })) } + (b'a'..=b'z') + .map(|c| format!("'{}", c as char)) + .find(|candidate| !used_names.iter().any(|e| e.as_str() == candidate)) + .unwrap_or("'lt".to_string()) }; - if let Some(origin) = origin { - self.note_region_origin(&mut err, &origin); - } - err + let mut visitor = LifetimeReplaceVisitor { + tcx: self.tcx, + needle: hir::LifetimeName::Param(lifetime_def_id), + add_lt_suggs, + new_lt: &new_lt, + }; + match self.tcx.hir().expect_owner(lifetime_scope) { + hir::OwnerNode::Item(i) => visitor.visit_item(i), + hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i), + hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i), + hir::OwnerNode::TraitItem(i) => visitor.visit_trait_item(i), + hir::OwnerNode::Crate(_) => bug!("OwnerNode::Crate doesn't not have generics"), + } + + let ast_generics = self.tcx.hir().get_generics(lifetime_scope).unwrap(); + let sugg = ast_generics + .span_for_lifetime_suggestion() + .map(|span| (span, format!("{new_lt}, "))) + .unwrap_or_else(|| (ast_generics.span, format!("<{new_lt}>"))); + add_lt_suggs.push(sugg); + + new_lt } fn report_sub_sup_conflict( @@ -2927,6 +2805,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { | IfExpression { .. } | LetElse | StartFunctionType + | LangFunctionType(_) | IntrinsicType | MethodReceiver => Error0308, @@ -2971,6 +2850,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags }, MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span }, StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags }, + &LangFunctionType(lang_item_name) => { + ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name } + } IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags }, MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags }, @@ -3006,6 +2888,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { IfExpressionWithNoElse => "`if` missing an `else` returns `()`", MainFunctionType => "`main` function has the correct type", StartFunctionType => "`#[start]` function has the correct type", + LangFunctionType(_) => "lang item function has the correct type", IntrinsicType => "intrinsic has the correct type", MethodReceiver => "method receiver has the correct type", _ => "types are compatible", @@ -3028,6 +2911,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> { IfExpressionWithNoElse => "no_else", MainFunctionType => "fn_main_correct_type", StartFunctionType => "fn_start_correct_type", + LangFunctionType(_) => "fn_lang_correct_type", IntrinsicType => "intrinsic_correct_type", MethodReceiver => "method_correct_type", _ => "other", 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 f2a3c47bdfe8e..e45108d1713a8 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 @@ -1,5 +1,5 @@ use crate::errors::{ - AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator, + AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, SourceKindMultiSuggestion, SourceKindSubdiag, }; use crate::infer::error_reporting::TypeErrCtxt; @@ -27,7 +27,7 @@ use std::iter; pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 - /// let x = "hello".chars().rev().collect(); + /// let x; /// ``` E0282, /// An implementation cannot be chosen unambiguously because of lack of information. @@ -595,39 +595,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } -impl<'tcx> InferCtxt<'tcx> { - pub fn need_type_info_err_in_generator( - &self, - kind: hir::GeneratorKind, - span: Span, - ty: ty::Term<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let ty = self.resolve_vars_if_possible(ty); - let data = self.extract_inference_diagnostics_data(ty.into(), None); - - NeedTypeInfoInGenerator { - bad_label: data.make_bad_error(span), - span, - generator_kind: GeneratorKindAsDiagArg(kind), - } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) - } -} - -pub struct GeneratorKindAsDiagArg(pub hir::GeneratorKind); - -impl IntoDiagnosticArg for GeneratorKindAsDiagArg { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - let kind = match self.0 { - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn", - hir::GeneratorKind::Gen => "generator", - }; - rustc_errors::DiagnosticArgValue::Str(kind.into()) - } -} - #[derive(Debug)] struct InferSource<'tcx> { span: Span, @@ -951,7 +918,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // // See the `need_type_info/issue-103053.rs` test for // a example. - if !matches!(path.res, Res::Def(DefKind::TyAlias { .. }, _)) => { + if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => { if let Some(ty) = self.opt_node_type(expr.hir_id) && let ty::Adt(_, args) = ty.kind() { @@ -1080,7 +1047,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { ) => { if tcx.res_generics_def_id(path.res) != Some(def.did()) { match path.res { - Res::Def(DefKind::TyAlias { .. }, _) => { + Res::Def(DefKind::TyAlias, _) => { // FIXME: Ideally we should support this. For that // we have to map back from the self type to the // type alias though. That's difficult. diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 07f04ec1e4449..1b43022f8f7d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let is_impl_item = region_info.is_impl_item; match br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {} + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon => {} _ => { /* not an anonymous region */ debug!("try_report_named_anon_conflict: not an anonymous region"); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs index 8a78a1956c997..f5b8912532b11 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -36,15 +36,13 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ty::BrNamed(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon(span) => (*span, None), - ty::BrEnv => (None, None), + ty::BrAnon | ty::BrEnv => (None, None), }; let (sup_span, sup_symbol) = match sup_name { ty::BrNamed(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon(span) => (*span, None), - ty::BrEnv => (None, None), + ty::BrAnon | ty::BrEnv => (None, None), }; let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) { (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => { 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 d2ba9966f0343..cb51254a14b0c 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 @@ -35,14 +35,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin) && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code() && sub_trace.values == sup_trace.values - && let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values + && let ValuePairs::PolySigs(ExpectedFound { expected, found }) = sub_trace.values { // FIXME(compiler-errors): Don't like that this needs `Ty`s, but // all of the region highlighting machinery only deals with those. let guar = self.emit_err( var_origin.span(), - Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(expected)), - Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(found)), + Ty::new_fn_ptr(self.cx.tcx, expected), + Ty::new_fn_ptr(self.cx.tcx, found), *trait_item_def_id, ); return Some(guar); 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 445f68160d286..5c3beee284fca 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 @@ -616,9 +616,13 @@ fn foo(&self) -> Self::T { String::new() } for item in &items[..] { if let hir::AssocItemKind::Type = item.kind { let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity(); - - if self.infcx.can_eq(param_env, assoc_ty, found) { - diag.span_label(item.span, "expected this associated type"); + if let hir::Defaultness::Default { has_value: true } = tcx.defaultness(item.id.owner_id) + && self.infcx.can_eq(param_env, assoc_ty, found) + { + diag.span_label( + item.span, + "associated type is `default` and may be overridden", + ); return true; } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4cf9d44ed65de..aeb3177af0275 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -383,7 +383,7 @@ pub enum ValuePairs<'tcx> { Aliases(ExpectedFound>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), - Sigs(ExpectedFound>), + PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), ExistentialProjection(ExpectedFound>), } diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 2ac9568f60be7..6a9d40daab62f 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -112,7 +112,7 @@ fn compute_components<'tcx>( } // All regions are bound inside a witness - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => (), + ty::GeneratorWitness(..) => (), // OutlivesTypeParameterEnv -- the actual checking that `X:'a` // is implied by the environment is done in regionck. diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index fefa8959545ab..2d6b88226adb2 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -44,7 +44,7 @@ pub fn extract_verify_if_eq<'tcx>( test_ty: Ty<'tcx>, ) -> Option> { assert!(!verify_if_eq_b.has_escaping_bound_vars()); - let mut m = Match::new(tcx, param_env); + let mut m = MatchAgainstHigherRankedOutlives::new(tcx, param_env); let verify_if_eq = verify_if_eq_b.skip_binder(); m.relate(verify_if_eq.ty, test_ty).ok()?; @@ -87,24 +87,32 @@ pub(super) fn can_match_erased_ty<'tcx>( // pointless micro-optimization true } else { - Match::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok() + MatchAgainstHigherRankedOutlives::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok() } } -struct Match<'tcx> { +struct MatchAgainstHigherRankedOutlives<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, pattern_depth: ty::DebruijnIndex, map: FxHashMap>, } -impl<'tcx> Match<'tcx> { - fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> { - Match { tcx, param_env, pattern_depth: ty::INNERMOST, map: FxHashMap::default() } +impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> MatchAgainstHigherRankedOutlives<'tcx> { + MatchAgainstHigherRankedOutlives { + tcx, + param_env, + pattern_depth: ty::INNERMOST, + map: FxHashMap::default(), + } } } -impl<'tcx> Match<'tcx> { +impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { /// Creates the "Error" variant that signals "no match". fn no_match(&self) -> RelateResult<'tcx, T> { Err(TypeError::Mismatch) @@ -134,7 +142,7 @@ impl<'tcx> Match<'tcx> { } } -impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { +impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> { fn tag(&self) -> &'static str { "Match" } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 27e1ed56f31a9..0c3bb633b53a9 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -147,25 +147,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { ); Ok(a) } - // Optimization of GeneratorWitness relation since we know that all - // free regions are replaced with bound regions during construction. - // This greatly speeds up subtyping of GeneratorWitness. - (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { - let a_types = infcx.tcx.anonymize_bound_vars(a_types); - let b_types = infcx.tcx.anonymize_bound_vars(b_types); - if a_types.bound_vars() == b_types.bound_vars() { - let (a_types, b_types) = infcx.instantiate_binder_with_placeholders( - a_types.map_bound(|a_types| (a_types, b_types.skip_binder())), - ); - for (a, b) in std::iter::zip(a_types, b_types) { - self.relate(a, b)?; - } - Ok(a) - } else { - Err(ty::error::TypeError::Sorts(ty::relate::expected_found(self, a, b))) - } - } - _ => { self.fields.infcx.super_combine_tys(self, a, b)?; Ok(a) diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index bc6d7c209971c..45b1aeb4a5c36 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -10,8 +10,10 @@ //! origin crate when the `TyCtxt` is not present in TLS. use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; -use rustc_middle::dep_graph::TaskDepsRef; +use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef}; use rustc_middle::ty::tls; +use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; +use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; use std::fmt; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { @@ -59,10 +61,49 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> write!(f, ")") } +/// This is a callback from `rustc_query_system` as it cannot access the implicit state +/// in `rustc_middle` otherwise. +pub fn dep_kind_debug(kind: DepKind, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + write!(f, "{}", tcx.dep_kind_info(kind).name) + } else { + default_dep_kind_debug(kind, f) + } + }) +} + +/// This is a callback from `rustc_query_system` as it cannot access the implicit state +/// in `rustc_middle` otherwise. +pub fn dep_node_debug(node: DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}(", node.kind)?; + + tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + if let Some(def_id) = node.extract_def_id(tcx) { + write!(f, "{}", tcx.def_path_debug_str(def_id))?; + } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(node) { + write!(f, "{s}")?; + } else { + write!(f, "{}", node.hash)?; + } + } else { + write!(f, "{}", node.hash)?; + } + Ok(()) + })?; + + write!(f, ")") +} + /// Sets up the callbacks in prior crates which we want to refer to the /// TyCtxt in. pub fn setup_callbacks() { rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + rustc_query_system::dep_graph::dep_node::DEP_KIND_DEBUG + .swap(&(dep_kind_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + rustc_query_system::dep_graph::dep_node::DEP_NODE_DEBUG + .swap(&(dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index a0f0b530baee1..1c330c064ab69 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -9,7 +9,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_lint::LintStore; -use rustc_middle::query::{ExternProviders, Providers}; +use rustc_middle::util::Providers; use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; @@ -37,7 +37,7 @@ pub struct Compiler { pub(crate) sess: Lrc, codegen_backend: Lrc, pub(crate) register_lints: Option>, - pub(crate) override_queries: Option, + pub(crate) override_queries: Option, } impl Compiler { @@ -271,7 +271,7 @@ pub struct Config { /// the list of queries. /// /// The second parameter is local providers and the third parameter is external providers. - pub override_queries: Option, + pub override_queries: Option, /// This is a callback from the driver that is called to create a codegen backend. pub make_codegen_backend: diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 51bd8381e93d7..76131c1ad69bd 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -25,7 +25,7 @@ pub mod util; pub use callbacks::setup_callbacks; pub use interface::{run_compiler, Config}; -pub use passes::{DEFAULT_EXTERN_QUERY_PROVIDERS, DEFAULT_QUERY_PROVIDERS}; +pub use passes::DEFAULT_QUERY_PROVIDERS; pub use queries::Queries; #[cfg(test)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e5ae6d5b5d6fb..0e8f93cef173f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,8 +18,8 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; +use rustc_middle::util::Providers; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{self, abi_test, hir_stats, layout_test}; @@ -675,13 +675,6 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { *providers }); -pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { - let mut extern_providers = ExternProviders::default(); - rustc_metadata::provide_extern(&mut extern_providers); - rustc_codegen_ssa::provide_extern(&mut extern_providers); - extern_providers -}); - pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, crate_types: Vec, @@ -702,14 +695,11 @@ pub fn create_global_ctxt<'tcx>( let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let codegen_backend = compiler.codegen_backend(); - let mut local_providers = *DEFAULT_QUERY_PROVIDERS; - codegen_backend.provide(&mut local_providers); - - let mut extern_providers = *DEFAULT_EXTERN_QUERY_PROVIDERS; - codegen_backend.provide_extern(&mut extern_providers); + let mut providers = *DEFAULT_QUERY_PROVIDERS; + codegen_backend.provide(&mut providers); if let Some(callback) = compiler.override_queries { - callback(sess, &mut local_providers, &mut extern_providers); + callback(sess, &mut providers); } let incremental = dep_graph.is_fully_enabled(); @@ -727,11 +717,12 @@ pub fn create_global_ctxt<'tcx>( dep_graph, rustc_query_impl::query_callbacks(arena), rustc_query_impl::query_system( - local_providers, - extern_providers, + providers.queries, + providers.extern_queries, query_result_on_disk_cache, incremental, ), + providers.hooks, ) }) }) @@ -807,14 +798,12 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { } }); - if tcx.sess.opts.unstable_opts.drop_tracking_mir { - tcx.hir().par_body_owners(|def_id| { - if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) { - tcx.ensure().mir_generator_witnesses(def_id); - tcx.ensure().check_generator_obligations(def_id); - } - }); - } + tcx.hir().par_body_owners(|def_id| { + if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) { + tcx.ensure().mir_generator_witnesses(def_id); + tcx.ensure().check_generator_obligations(def_id); + } + }); sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 449d7a295904e..fe253febfc787 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -10,7 +10,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal}; use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; -use rustc_incremental::DepGraphFuture; +use rustc_incremental::setup_dep_graph; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -19,7 +19,6 @@ use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; use rustc_session::{output::find_crate_name, Session}; use rustc_span::symbol::sym; -use rustc_span::Symbol; use std::any::Any; use std::cell::{RefCell, RefMut}; use std::sync::Arc; @@ -132,43 +131,6 @@ impl<'tcx> Queries<'tcx> { }) } - fn dep_graph_future( - &self, - crate_name: Symbol, - stable_crate_id: StableCrateId, - ) -> Result> { - let sess = self.session(); - - // `load_dep_graph` can only be called after `prepare_session_directory`. - rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?; - let res = sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess)); - - if sess.opts.incremental.is_some() { - sess.time("incr_comp_garbage_collect_session_directories", || { - if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { - warn!( - "Error while trying to garbage collect incremental \ - compilation cache directory: {}", - e - ); - } - }); - } - - Ok(res) - } - - fn dep_graph(&self, dep_graph_future: Option) -> DepGraph { - dep_graph_future - .and_then(|future| { - let sess = self.session(); - let (prev_graph, prev_work_products) = - sess.time("blocked_on_dep_graph_loading", || future.open().open(sess)); - rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products) - }) - .unwrap_or_else(DepGraph::new_disabled) - } - pub fn global_ctxt(&'tcx self) -> Result>> { self.gcx.compute(|| { let sess = self.session(); @@ -184,10 +146,7 @@ impl<'tcx> Queries<'tcx> { sess.opts.cg.metadata.clone(), sess.cfg_version, ); - - // Compute the dependency graph (in the background). We want to do this as early as - // possible, to give the DepGraph maximum time to load before `dep_graph` is called. - let dep_graph_future = self.dep_graph_future(crate_name, stable_crate_id)?; + let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; let lint_store = Lrc::new(passes::create_lint_store( sess, @@ -210,7 +169,7 @@ impl<'tcx> Queries<'tcx> { crate_types, stable_crate_id, lint_store, - self.dep_graph(dep_graph_future), + dep_graph, untracked, &self.gcx_cell, &self.arena, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 1746cc8b71916..2510ce7146022 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -684,7 +684,6 @@ fn test_unstable_options_tracking_hash() { untracked!(dep_tasks, true); untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); - untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string())); untracked!(dump_mir, Some(String::from("abc"))); untracked!(dump_mir_dataflow, true); untracked!(dump_mir_dir, String::from("abc")); @@ -773,7 +772,6 @@ fn test_unstable_options_tracking_hash() { tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); - tracked!(drop_tracking, true); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); tracked!(emit_thin_lto, false); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7377c6e2f35a2..fa4b8e4c36b84 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -5,6 +5,10 @@ lint_array_into_iter = .use_explicit_into_iter_suggestion = or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value +lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified + .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` + .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send` + lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` @@ -319,6 +323,8 @@ lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undef lint_invalid_reference_casting_note_book = for more information, visit +lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get` + lint_lintpass_by_hand = implementing `LintPass` by hand .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index d0967ba564402..814991cd8c971 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -34,8 +34,8 @@ declare_lint! { Warn, "detects calling `into_iter` on arrays in Rust 2015 and 2018", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), + reference: "", }; } diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs new file mode 100644 index 0000000000000..ff4c81e2fc9b1 --- /dev/null +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -0,0 +1,128 @@ +use crate::lints::AsyncFnInTraitDiag; +use crate::LateContext; +use crate::LateLintPass; +use rustc_hir as hir; +use rustc_trait_selection::traits::error_reporting::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait; + +declare_lint! { + /// The `async_fn_in_trait` lint detects use of `async fn` in the + /// definition of a publicly-reachable trait. + /// + /// ### Example + /// + /// ```rust + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self); + /// } + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// When `async fn` is used in a trait definition, the trait does not + /// promise that the opaque [`Future`] returned by the associated function + /// or method will implement any [auto traits] such as [`Send`]. This may + /// be surprising and may make the associated functions or methods on the + /// trait less useful than intended. On traits exposed publicly from a + /// crate, this may affect downstream crates whose authors cannot alter + /// the trait definition. + /// + /// For example, this code is invalid: + /// + /// ```rust,compile_fail + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self) {} + /// } + /// + /// fn test(x: T) { + /// fn spawn(_: T) {} + /// spawn(x.method()); // Not OK. + /// } + /// ``` + /// + /// This lint exists to warn authors of publicly-reachable traits that + /// they may want to consider desugaring the `async fn` to a normal `fn` + /// that returns an opaque `impl Future<..> + Send` type. + /// + /// For example, instead of: + /// + /// ```rust + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self) {} + /// } + /// ``` + /// + /// The author of the trait may want to write: + /// + /// + /// ```rust + /// # #![feature(return_position_impl_trait_in_trait)] + /// use core::future::Future; + /// pub trait Trait { + /// fn method(&self) -> impl Future + Send { async {} } + /// } + /// ``` + /// + /// This still allows the use of `async fn` within impls of the trait. + /// However, it also means that the trait will never be compatible with + /// impls where the returned [`Future`] of the method does not implement + /// `Send`. + /// + /// Conversely, if the trait is used only locally, if it is never used in + /// generic functions, or if it is only used in single-threaded contexts + /// that do not care whether the returned [`Future`] implements [`Send`], + /// then the lint may be suppressed. + /// + /// [`Future`]: https://doc.rust-lang.org/core/future/trait.Future.html + /// [`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html + /// [auto traits]: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits + pub ASYNC_FN_IN_TRAIT, + Warn, + "use of `async fn` in definition of a publicly-reachable trait" +} + +declare_lint_pass!( + /// Lint for use of `async fn` in the definition of a publicly-reachable + /// trait. + AsyncFnInTrait => [ASYNC_FN_IN_TRAIT] +); + +impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) { + if let hir::TraitItemKind::Fn(sig, body) = item.kind + && let hir::IsAsync::Async(async_span) = sig.header.asyncness + { + // RTN can be used to bound `async fn` in traits in a better way than "always" + if cx.tcx.features().return_type_notation { + return; + } + + // Only need to think about library implications of reachable traits + if !cx.tcx.effective_visibilities(()).is_reachable(item.owner_id.def_id) { + return; + } + + let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) = + sig.decl.output + else { + // This should never happen, but let's not ICE. + return; + }; + let sugg = suggest_desugaring_async_fn_to_impl_future_in_trait( + cx.tcx, + sig, + body, + def.owner_id.def_id, + " + Send", + ); + cx.tcx.emit_spanned_lint(ASYNC_FN_IN_TRAIT, item.hir_id(), async_span, AsyncFnInTraitDiag { + sugg + }); + } + } +} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index de228bdb85030..536f78a73edb6 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -41,7 +41,6 @@ use crate::{ }, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, }; -use hir::IsAsync; use rustc_ast::attr; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; @@ -845,8 +844,8 @@ declare_lint! { Warn, "detects anonymous parameters", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #41686 ", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), + reference: "issue #41686 ", }; } @@ -1294,7 +1293,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller { span: Span, def_id: LocalDefId, ) { - if fn_kind.asyncness() == IsAsync::Async + if fn_kind.asyncness().is_async() && !cx.tcx.features().async_fn_track_caller // Now, check if the function has the `#[track_caller]` attribute && let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller) @@ -1455,13 +1454,13 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return }; - if cx.tcx.features().lazy_type_alias { - // Bounds of lazy type aliases are respected. + // Bounds of lazy type aliases and TAITs are respected. + if cx.tcx.type_alias_is_lazy(item.owner_id) { return; } let ty = cx.tcx.type_of(item.owner_id).skip_binder(); - if ty.has_opaque_types() || ty.has_inherent_projections() { + if ty.has_inherent_projections() { // Bounds of type aliases that contain opaque types or inherent projections are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`. return; @@ -1670,8 +1669,8 @@ declare_lint! { Warn, "`...` range patterns are deprecated", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + reference: "", }; } @@ -1805,8 +1804,8 @@ declare_lint! { Allow, "detects edition keywords being used as an identifier", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #49716 ", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), + reference: "issue #49716 ", }; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7a336a8f69474..3c5cde4309b44 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1315,6 +1315,91 @@ impl<'tcx> LateContext<'tcx> { tcx.try_normalize_erasing_regions(self.param_env, proj).ok() }) } + + /// If the given expression is a local binding, find the initializer expression. + /// If that initializer expression is another local binding, find its initializer again. + /// + /// This process repeats as long as possible (but usually no more than once). + /// Type-check adjustments are not taken in account in this function. + /// + /// Examples: + /// ``` + /// let abc = 1; + /// let def = abc + 2; + /// // ^^^^^^^ output + /// let def = def; + /// dbg!(def); + /// // ^^^ input + /// ``` + pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> { + expr = expr.peel_blocks(); + + while let hir::ExprKind::Path(ref qpath) = expr.kind + && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) { + Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id), + _ => None, + } + && let Some(init) = match parent_node { + hir::Node::Expr(expr) => Some(expr), + hir::Node::Local(hir::Local { init, .. }) => *init, + _ => None + } + { + expr = init.peel_blocks(); + } + expr + } + + /// If the given expression is a local binding, find the initializer expression. + /// If that initializer expression is another local or **outside** (`const`/`static`) + /// binding, find its initializer again. + /// + /// This process repeats as long as possible (but usually no more than once). + /// Type-check adjustments are not taken in account in this function. + /// + /// Examples: + /// ``` + /// const ABC: i32 = 1; + /// // ^ output + /// let def = ABC; + /// dbg!(def); + /// // ^^^ input + /// + /// // or... + /// let abc = 1; + /// let def = abc + 2; + /// // ^^^^^^^ output + /// dbg!(def); + /// // ^^^ input + /// ``` + pub fn expr_or_init_with_outside_body<'a>( + &self, + mut expr: &'a hir::Expr<'tcx>, + ) -> &'a hir::Expr<'tcx> { + expr = expr.peel_blocks(); + + while let hir::ExprKind::Path(ref qpath) = expr.kind + && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) { + Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id), + Res::Def(_, def_id) => self.tcx.hir().get_if_local(def_id), + _ => None, + } + && let Some(init) = match parent_node { + hir::Node::Expr(expr) => Some(expr), + hir::Node::Local(hir::Local { init, .. }) => *init, + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => { + Some(self.tcx.hir().body(body_id).value) + } + _ => None + } + _ => None + } + { + expr = init.peel_blocks(); + } + expr + } } impl<'tcx> abi::HasDataLayout for LateContext<'tcx> { diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 851c6493daf9b..9be2edf845334 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -5,6 +5,7 @@ use crate::{ use rustc_hir as hir; use rustc_middle::{traits::util::supertraits, ty}; +use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::sym; declare_lint! { @@ -48,6 +49,7 @@ declare_lint! { Warn, "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #89460 ", }; } diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 7b291d558e03b..e1df69bdaf252 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -5,19 +5,18 @@ use rustc_hir::def::DefKind; use rustc_middle::query::Providers; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_session::lint::{lint_array, LintArray}; use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::FIRST_VARIANT; use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub}; -use crate::types; +use crate::{types, LintVec}; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { clashing_extern_declarations, ..*providers }; } -pub(crate) fn get_lints() -> LintArray { - lint_array!(CLASHING_EXTERN_DECLARATIONS) +pub(crate) fn get_lints() -> LintVec { + vec![CLASHING_EXTERN_DECLARATIONS] } fn clashing_extern_declarations(tcx: TyCtxt<'_>, (): ()) { diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index 3291286ad679b..e398059ade9fc 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -1,6 +1,6 @@ use std::str::Utf8Error; -use rustc_ast::{BorrowKind, LitKind}; +use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -11,7 +11,7 @@ use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `invalid_from_utf8_unchecked` lint checks for calls to /// `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut` - /// with an invalid UTF-8 literal. + /// with a known invalid UTF-8 value. /// /// ### Example /// @@ -36,7 +36,7 @@ declare_lint! { declare_lint! { /// The `invalid_from_utf8` lint checks for calls to /// `std::str::from_utf8` and `std::str::from_utf8_mut` - /// with an invalid UTF-8 literal. + /// with a known invalid UTF-8 value. /// /// ### Example /// @@ -67,8 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { && [sym::str_from_utf8, sym::str_from_utf8_mut, sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item) { - let lint = |utf8_error: Utf8Error| { - let label = arg.span; + let lint = |label, utf8_error: Utf8Error| { let method = diag_item.as_str().strip_prefix("str_").unwrap(); let method = format!("std::str::{method}"); let valid_up_to = utf8_error.valid_up_to(); @@ -78,22 +77,26 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { if is_unchecked_variant { INVALID_FROM_UTF8_UNCHECKED } else { INVALID_FROM_UTF8 }, expr.span, if is_unchecked_variant { - InvalidFromUtf8Diag::Unchecked { method, valid_up_to, label } + InvalidFromUtf8Diag::Unchecked { method, valid_up_to, label } } else { - InvalidFromUtf8Diag::Checked { method, valid_up_to, label } + InvalidFromUtf8Diag::Checked { method, valid_up_to, label } } ) }; - match &arg.kind { + let mut init = cx.expr_or_init_with_outside_body(arg); + while let ExprKind::AddrOf(.., inner) = init.kind { + init = cx.expr_or_init_with_outside_body(inner); + } + match init.kind { ExprKind::Lit(Spanned { node: lit, .. }) => { if let LitKind::ByteStr(bytes, _) = &lit && let Err(utf8_error) = std::str::from_utf8(bytes) { - lint(utf8_error); + lint(init.span, utf8_error); } }, - ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => { + ExprKind::Array(args) => { let elements = args.iter().map(|e|{ match &e.kind { ExprKind::Lit(Spanned { node: lit, .. }) => match lit { @@ -108,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { if let Some(elements) = elements && let Err(utf8_error) = std::str::from_utf8(&elements) { - lint(utf8_error); + lint(init.span, utf8_error); } } _ => {} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 84434d585d3d6..af2132fb8997a 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_session; extern crate tracing; mod array_into_iter; +mod async_fn_in_trait; pub mod builtin; mod context; mod deref_into_dyn_supertrait; @@ -86,20 +87,17 @@ mod unused; pub use array_into_iter::ARRAY_INTO_ITER; -use rustc_ast as ast; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; -use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; +use rustc_hir::def_id::LocalModDefId; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::{ BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS, }; -use rustc_span::symbol::Ident; -use rustc_span::Span; use array_into_iter::ArrayIntoIter; +use async_fn_in_trait::AsyncFnInTrait; use builtin::*; use deref_into_dyn_supertrait::*; use drop_forget_useless::*; @@ -134,7 +132,7 @@ pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; -pub use rustc_session::lint::{LintArray, LintPass}; +pub use rustc_session::lint::{LintPass, LintVec}; fluent_messages! { "../messages.ftl" } @@ -200,7 +198,7 @@ late_lint_methods!( BoxPointers: BoxPointers, PathStatements: PathStatements, LetUnderscore: LetUnderscore, - InvalidReferenceCasting: InvalidReferenceCasting::default(), + InvalidReferenceCasting: InvalidReferenceCasting, // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, NonUpperCaseGlobals: NonUpperCaseGlobals, @@ -238,6 +236,7 @@ late_lint_methods!( MapUnitFn: MapUnitFn, MissingDebugImplementations: MissingDebugImplementations, MissingDoc: MissingDoc, + AsyncFnInTrait: AsyncFnInTrait, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c091c260a470e..c776d3bb7fed6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -771,12 +771,16 @@ pub enum InvalidReferenceCastingDiag { BorrowAsMut { #[label] orig_cast: Option, + #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + ty_has_interior_mutability: Option<()>, }, #[diag(lint_invalid_reference_casting_assign_to_ref)] #[note(lint_invalid_reference_casting_note_book)] AssignToRef { #[label] orig_cast: Option, + #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + ty_has_interior_mutability: Option<()>, }, } @@ -1818,3 +1822,24 @@ pub struct UnusedAllocationDiag; #[derive(LintDiagnostic)] #[diag(lint_unused_allocation_mut)] pub struct UnusedAllocationMutDiag; + +pub struct AsyncFnInTraitDiag { + pub sugg: Option>, +} + +impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.note(fluent::lint_note); + if let Some(sugg) = self.sugg { + diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); + } + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_async_fn_in_trait + } +} diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index bc0b9d6d81871..cfbca6efbfa54 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -98,6 +98,12 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, cx.param_env, did, args) else { return }; // (Re)check that it implements the noop diagnostic. let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; + if !matches!( + name, + sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref + ) { + return; + } let receiver_ty = cx.typeck_results().expr_ty(receiver); let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 79b0b32bef248..c24846ca93988 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -37,8 +37,6 @@ declare_lint! { /// type Assoc: Duh; /// } /// - /// struct Struct; - /// /// impl Trait for F { /// type Assoc = F; /// } @@ -53,12 +51,12 @@ declare_lint! { /// {{produces}} /// /// In this example, `test` declares that the associated type `Assoc` for - /// `impl Trait` is `impl Sized`, which does not satisfy the `Send` bound + /// `impl Trait` is `impl Sized`, which does not satisfy the bound `Duh` /// on the associated type. /// /// Although the hidden type, `i32` does satisfy this bound, we do not /// consider the return type to be well-formed with this lint. It can be - /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`. + /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Duh`. pub OPAQUE_HIDDEN_INFERRED_BOUND, Warn, "detects the use of nested `impl Trait` types in associated type bounds that are not general enough" @@ -79,9 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { - // Liberate bound regions in the predicate since we - // don't actually care about lifetimes in this check. - let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); + let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); let ty::ClauseKind::Projection(proj) = predicate else { continue; }; diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index fca0eeeecc4b7..508f3e1ec3106 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -1,58 +1,53 @@ use crate::context::{EarlyContext, LateContext}; -use rustc_ast as ast; -use rustc_hir as hir; use rustc_session::lint::builtin::HardwiredLints; use rustc_session::lint::LintPass; -use rustc_span::def_id::LocalDefId; -use rustc_span::symbol::Ident; -use rustc_span::Span; #[macro_export] macro_rules! late_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ - fn check_body(a: &'tcx hir::Body<'tcx>); - fn check_body_post(a: &'tcx hir::Body<'tcx>); + fn check_body(a: &'tcx rustc_hir::Body<'tcx>); + fn check_body_post(a: &'tcx rustc_hir::Body<'tcx>); fn check_crate(); fn check_crate_post(); - fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId); - fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>); - fn check_item(a: &'tcx hir::Item<'tcx>); - fn check_item_post(a: &'tcx hir::Item<'tcx>); - fn check_local(a: &'tcx hir::Local<'tcx>); - fn check_block(a: &'tcx hir::Block<'tcx>); - fn check_block_post(a: &'tcx hir::Block<'tcx>); - fn check_stmt(a: &'tcx hir::Stmt<'tcx>); - fn check_arm(a: &'tcx hir::Arm<'tcx>); - fn check_pat(a: &'tcx hir::Pat<'tcx>); - fn check_expr(a: &'tcx hir::Expr<'tcx>); - fn check_expr_post(a: &'tcx hir::Expr<'tcx>); - fn check_ty(a: &'tcx hir::Ty<'tcx>); - fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>); - fn check_generics(a: &'tcx hir::Generics<'tcx>); - fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>); + fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_hir::HirId); + fn check_foreign_item(a: &'tcx rustc_hir::ForeignItem<'tcx>); + fn check_item(a: &'tcx rustc_hir::Item<'tcx>); + fn check_item_post(a: &'tcx rustc_hir::Item<'tcx>); + fn check_local(a: &'tcx rustc_hir::Local<'tcx>); + fn check_block(a: &'tcx rustc_hir::Block<'tcx>); + fn check_block_post(a: &'tcx rustc_hir::Block<'tcx>); + fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>); + fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>); + fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>); + fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>); + fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>); + fn check_ty(a: &'tcx rustc_hir::Ty<'tcx>); + fn check_generic_param(a: &'tcx rustc_hir::GenericParam<'tcx>); + fn check_generics(a: &'tcx rustc_hir::Generics<'tcx>); + fn check_poly_trait_ref(a: &'tcx rustc_hir::PolyTraitRef<'tcx>); fn check_fn( a: rustc_hir::intravisit::FnKind<'tcx>, - b: &'tcx hir::FnDecl<'tcx>, - c: &'tcx hir::Body<'tcx>, - d: Span, - e: LocalDefId); - fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>); - fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>); - fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>); - fn check_struct_def(a: &'tcx hir::VariantData<'tcx>); - fn check_field_def(a: &'tcx hir::FieldDef<'tcx>); - fn check_variant(a: &'tcx hir::Variant<'tcx>); - fn check_path(a: &hir::Path<'tcx>, b: hir::HirId); - fn check_attribute(a: &'tcx ast::Attribute); + b: &'tcx rustc_hir::FnDecl<'tcx>, + c: &'tcx rustc_hir::Body<'tcx>, + d: rustc_span::Span, + e: rustc_span::def_id::LocalDefId); + fn check_trait_item(a: &'tcx rustc_hir::TraitItem<'tcx>); + fn check_impl_item(a: &'tcx rustc_hir::ImplItem<'tcx>); + fn check_impl_item_post(a: &'tcx rustc_hir::ImplItem<'tcx>); + fn check_struct_def(a: &'tcx rustc_hir::VariantData<'tcx>); + fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>); + fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>); + fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId); + fn check_attribute(a: &'tcx rustc_ast::Attribute); /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. - fn enter_lint_attrs(a: &'tcx [ast::Attribute]); + fn enter_lint_attrs(a: &'tcx [rustc_ast::Attribute]); /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(a: &'tcx [ast::Attribute]); + fn exit_lint_attrs(a: &'tcx [rustc_ast::Attribute]); ]); ) } @@ -90,8 +85,8 @@ macro_rules! expand_combined_late_lint_pass_method { #[macro_export] macro_rules! expand_combined_late_lint_pass_methods { ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) { - expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); + $(fn $name(&mut self, context: &$crate::LateContext<'tcx>, $($param: $arg),*) { + $crate::expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* ) } @@ -116,19 +111,19 @@ macro_rules! declare_combined_late_lint_pass { } } - $v fn get_lints() -> LintArray { + $v fn get_lints() -> $crate::LintVec { let mut lints = Vec::new(); $(lints.extend_from_slice(&$pass::get_lints());)* lints } } - impl<'tcx> LateLintPass<'tcx> for $name { - expand_combined_late_lint_pass_methods!([$($pass),*], $methods); + impl<'tcx> $crate::LateLintPass<'tcx> for $name { + $crate::expand_combined_late_lint_pass_methods!([$($pass),*], $methods); } #[allow(rustc::lint_pass_impl_without_macro)] - impl LintPass for $name { + impl $crate::LintPass for $name { fn name(&self) -> &'static str { panic!() } @@ -140,42 +135,45 @@ macro_rules! declare_combined_late_lint_pass { macro_rules! early_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ - fn check_param(a: &ast::Param); - fn check_ident(a: Ident); - fn check_crate(a: &ast::Crate); - fn check_crate_post(a: &ast::Crate); - fn check_item(a: &ast::Item); - fn check_item_post(a: &ast::Item); - fn check_local(a: &ast::Local); - fn check_block(a: &ast::Block); - fn check_stmt(a: &ast::Stmt); - fn check_arm(a: &ast::Arm); - fn check_pat(a: &ast::Pat); - fn check_pat_post(a: &ast::Pat); - fn check_expr(a: &ast::Expr); - fn check_expr_post(a: &ast::Expr); - fn check_ty(a: &ast::Ty); - fn check_generic_arg(a: &ast::GenericArg); - fn check_generic_param(a: &ast::GenericParam); - fn check_generics(a: &ast::Generics); - fn check_poly_trait_ref(a: &ast::PolyTraitRef); - fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId); - fn check_trait_item(a: &ast::AssocItem); - fn check_impl_item(a: &ast::AssocItem); - fn check_variant(a: &ast::Variant); - fn check_attribute(a: &ast::Attribute); - fn check_mac_def(a: &ast::MacroDef); - fn check_mac(a: &ast::MacCall); + fn check_param(a: &rustc_ast::Param); + fn check_ident(a: rustc_span::symbol::Ident); + fn check_crate(a: &rustc_ast::Crate); + fn check_crate_post(a: &rustc_ast::Crate); + fn check_item(a: &rustc_ast::Item); + fn check_item_post(a: &rustc_ast::Item); + fn check_local(a: &rustc_ast::Local); + fn check_block(a: &rustc_ast::Block); + fn check_stmt(a: &rustc_ast::Stmt); + fn check_arm(a: &rustc_ast::Arm); + fn check_pat(a: &rustc_ast::Pat); + fn check_pat_post(a: &rustc_ast::Pat); + fn check_expr(a: &rustc_ast::Expr); + fn check_expr_post(a: &rustc_ast::Expr); + fn check_ty(a: &rustc_ast::Ty); + fn check_generic_arg(a: &rustc_ast::GenericArg); + fn check_generic_param(a: &rustc_ast::GenericParam); + fn check_generics(a: &rustc_ast::Generics); + fn check_poly_trait_ref(a: &rustc_ast::PolyTraitRef); + fn check_fn( + a: rustc_ast::visit::FnKind<'_>, + c: rustc_span::Span, + d_: rustc_ast::NodeId); + fn check_trait_item(a: &rustc_ast::AssocItem); + fn check_impl_item(a: &rustc_ast::AssocItem); + fn check_variant(a: &rustc_ast::Variant); + fn check_attribute(a: &rustc_ast::Attribute); + fn check_mac_def(a: &rustc_ast::MacroDef); + fn check_mac(a: &rustc_ast::MacCall); /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. - fn enter_lint_attrs(a: &[ast::Attribute]); + fn enter_lint_attrs(a: &[rustc_ast::Attribute]); /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(a: &[ast::Attribute]); + fn exit_lint_attrs(a: &[rustc_ast::Attribute]); - fn enter_where_predicate(a: &ast::WherePredicate); - fn exit_where_predicate(a: &ast::WherePredicate); + fn enter_where_predicate(a: &rustc_ast::WherePredicate); + fn exit_where_predicate(a: &rustc_ast::WherePredicate); ]); ) } @@ -202,8 +200,8 @@ macro_rules! expand_combined_early_lint_pass_method { #[macro_export] macro_rules! expand_combined_early_lint_pass_methods { ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { - expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*)); + $(fn $name(&mut self, context: &$crate::EarlyContext<'_>, $($param: $arg),*) { + $crate::expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* ) } @@ -228,19 +226,19 @@ macro_rules! declare_combined_early_lint_pass { } } - $v fn get_lints() -> LintArray { + $v fn get_lints() -> $crate::LintVec { let mut lints = Vec::new(); $(lints.extend_from_slice(&$pass::get_lints());)* lints } } - impl EarlyLintPass for $name { - expand_combined_early_lint_pass_methods!([$($pass),*], $methods); + impl $crate::EarlyLintPass for $name { + $crate::expand_combined_early_lint_pass_methods!([$($pass),*], $methods); } #[allow(rustc::lint_pass_impl_without_macro)] - impl LintPass for $name { + impl $crate::LintPass for $name { fn name(&self) -> &'static str { panic!() } diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d540f473ae8f1..0c52fbaf78ca2 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -1,8 +1,7 @@ use rustc_ast::Mutability; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, QPath, StmtKind, UnOp}; +use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_middle::ty::{self, TypeAndMut}; -use rustc_span::{sym, Span}; +use rustc_span::sym; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; @@ -34,49 +33,29 @@ declare_lint! { "casts of `&T` to `&mut T` without interior mutability" } -#[derive(Default)] -pub struct InvalidReferenceCasting { - casted: FxHashMap, -} - -impl_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); +declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { - fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) { - let StmtKind::Local(local) = stmt.kind else { - return; - }; - let Local { init: Some(init), els: None, .. } = local else { - return; - }; - - if is_cast_from_const_to_mut(cx, init) { - self.casted.insert(local.pat.hir_id, init.span); - } - } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else { return; }; - let orig_cast = if is_cast_from_const_to_mut(cx, e) { - None - } else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind - && let Res::Local(hir_id) = &path.res - && let Some(orig_cast) = self.casted.get(hir_id) { - Some(*orig_cast) - } else { + let init = cx.expr_or_init(e); + + let Some(ty_has_interior_mutability) = is_cast_from_const_to_mut(cx, init) else { return; }; + let orig_cast = if init.span != e.span { Some(init.span) } else { None }; + let ty_has_interior_mutability = ty_has_interior_mutability.then_some(()); cx.emit_spanned_lint( INVALID_REFERENCE_CASTING, expr.span, if is_assignment { - InvalidReferenceCastingDiag::AssignToRef { orig_cast } + InvalidReferenceCastingDiag::AssignToRef { orig_cast, ty_has_interior_mutability } } else { - InvalidReferenceCastingDiag::BorrowAsMut { orig_cast } + InvalidReferenceCastingDiag::BorrowAsMut { orig_cast, ty_has_interior_mutability } }, ); } @@ -125,109 +104,65 @@ fn is_operation_we_care_about<'tcx>( deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e)) } -fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { - let e = e.peel_blocks(); +fn is_cast_from_const_to_mut<'tcx>( + cx: &LateContext<'tcx>, + orig_expr: &'tcx Expr<'tcx>, +) -> Option { + let mut need_check_freeze = false; + let mut e = orig_expr; - fn from_casts<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'tcx>, - need_check_freeze: &mut bool, - ) -> Option<&'tcx Expr<'tcx>> { - // as *mut ... - let mut e = if let ExprKind::Cast(e, t) = e.kind - && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { - e - // .cast_mut() + let end_ty = cx.typeck_results().node_type(orig_expr.hir_id); + + // Bail out early if the end type is **not** a mutable pointer. + if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) { + return None; + } + + loop { + e = e.peel_blocks(); + // as ... + e = if let ExprKind::Cast(expr, _) = e.kind { + expr + // .cast(), .cast_mut() or .cast_const() } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) + ) + { expr - // UnsafeCell::raw_get() + // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() } else if let ExprKind::Call(path, [arg]) = e.kind && let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) + ) { - *need_check_freeze = true; + if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { + need_check_freeze = true; + } arg } else { - return None; + break; }; - - let mut had_at_least_one_cast = false; - loop { - e = e.peel_blocks(); - // as *mut/const ... or as - e = if let ExprKind::Cast(expr, t) = e.kind - && matches!(cx.typeck_results().node_type(t.hir_id).kind(), ty::RawPtr(_) | ty::Uint(_)) { - had_at_least_one_cast = true; - expr - // .cast(), .cast_mut() or .cast_const() - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) - ) - { - had_at_least_one_cast = true; - expr - // ptr::from_ref() or UnsafeCell::raw_get() - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get) - ) - { - if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { - *need_check_freeze = true; - } - return Some(arg); - } else if had_at_least_one_cast { - return Some(e); - } else { - return None; - }; - } - } - - fn from_transmute<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'tcx>, - ) -> Option<&'tcx Expr<'tcx>> { - // mem::transmute::<_, *mut _>() - if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::transmute, def_id) - && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(e.hir_id).kind() { - Some(arg) - } else { - None - } } - let mut need_check_freeze = false; - let Some(e) = from_casts(cx, e, &mut need_check_freeze).or_else(|| from_transmute(cx, e)) - else { - return false; - }; - - let e = e.peel_blocks(); - let node_type = cx.typeck_results().node_type(e.hir_id); - if let ty::Ref(_, inner_ty, Mutability::Not) = node_type.kind() { + let start_ty = cx.typeck_results().node_type(e.hir_id); + if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() { // If an UnsafeCell method is involved we need to additionaly check the // inner type for the presence of the Freeze trait (ie does NOT contain // an UnsafeCell), since in that case we would incorrectly lint on valid casts. // // We also consider non concrete skeleton types (ie generics) // to be an issue since there is no way to make it safe for abitrary types. - !need_check_freeze - || inner_ty.is_freeze(cx.tcx, cx.param_env) - || !inner_ty.has_concrete_skeleton() + let inner_ty_has_interior_mutability = + !inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton(); + (!need_check_freeze || !inner_ty_has_interior_mutability) + .then_some(inner_ty_has_interior_mutability) } else { - false + None } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 57c2e289f205f..44cf1591c7d4a 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1271,7 +1271,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Placeholder(..) | ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty), } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 860366fdd6185..69b462d32bd55 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -39,6 +39,7 @@ declare_lint! { Warn, "applying forbid to lint-groups", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #81670 ", }; } @@ -74,6 +75,7 @@ declare_lint! { Deny, "ill-formed attribute inputs that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #57571 ", }; crate_level_only @@ -110,6 +112,7 @@ declare_lint! { Deny, "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #68585 ", }; } @@ -303,6 +306,7 @@ declare_lint! { /// pub async fn uhoh() { /// let guard = SyncThing {}; /// yield_now().await; + /// let _guard = guard; /// } /// ``` /// @@ -1016,8 +1020,8 @@ declare_lint! { Deny, "raw pointers must be aligned before dereferencing", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #68585 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -1096,6 +1100,7 @@ declare_lint! { Deny, "detect public re-exports of private extern crates", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #34537 ", }; } @@ -1125,6 +1130,7 @@ declare_lint! { Deny, "type parameter default erroneously allowed in invalid location", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #36887 ", }; } @@ -1267,6 +1273,7 @@ declare_lint! { Deny, "patterns in functions without body were erroneously allowed", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #35203 ", }; } @@ -1310,6 +1317,7 @@ declare_lint! { Deny, "detects missing fragment specifiers in unused `macro_rules!` patterns", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #40107 ", }; } @@ -1351,6 +1359,7 @@ declare_lint! { Warn, "detects generic lifetime arguments in path segments with late bound lifetime parameters", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #42868 ", }; } @@ -1386,8 +1395,8 @@ declare_lint! { Deny, "trait-object types were treated as different depending on marker-trait order", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #56484 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -1426,6 +1435,7 @@ declare_lint! { Warn, "distinct impls distinguished only by the leak-check code", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #56105 ", }; } @@ -1617,8 +1627,8 @@ declare_lint! { Warn, "raw pointer to an inference variable", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46906 ", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), + reference: "issue #46906 ", }; } @@ -1685,8 +1695,8 @@ declare_lint! { Warn, "suggest using `dyn Trait` for trait objects", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + reference: "", }; } @@ -1740,8 +1750,8 @@ declare_lint! { "fully qualified paths that start with a module name \ instead of `crate`, `self`, or an extern crate name", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #53130 ", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), + reference: "issue #53130 ", }; } @@ -1789,6 +1799,7 @@ declare_lint! { Warn, "floating-point literals cannot be used in patterns", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #41620 ", }; } @@ -1939,6 +1950,7 @@ declare_lint! { Warn, "checks the object safety of where clauses", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #51443 ", }; } @@ -2005,8 +2017,8 @@ declare_lint! { Deny, "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #83583 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -2108,6 +2120,7 @@ declare_lint! { "macro-expanded `macro_export` macros from the current crate \ cannot be referred to by absolute paths", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #52234 ", }; crate_level_only @@ -2199,6 +2212,7 @@ declare_lint! { Warn, "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #62411 ", }; } @@ -2253,6 +2267,7 @@ declare_lint! { Allow, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #62411 ", }; } @@ -2291,10 +2306,62 @@ declare_lint! { "constant used in pattern of non-structural-match type and the constant's initializer \ expression contains values of non-structural-match types", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #73448 ", }; } +declare_lint! { + /// The `const_patterns_without_partial_eq` lint detects constants that are used in patterns, + /// whose type does not implement `PartialEq`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(const_patterns_without_partial_eq)] + /// + /// trait EnumSetType { + /// type Repr; + /// } + /// + /// enum Enum8 { } + /// impl EnumSetType for Enum8 { + /// type Repr = u8; + /// } + /// + /// #[derive(PartialEq, Eq)] + /// struct EnumSet { + /// __enumset_underlying: T::Repr, + /// } + /// + /// const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; + /// + /// fn main() { + /// match CONST_SET { + /// CONST_SET => { /* ok */ } + /// _ => panic!("match fell through?"), + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust accepted constants in patterns, even if those constants' types + /// did not have `PartialEq` implemented. The compiler falls back to comparing the value + /// field-by-field. In the future we'd like to ensure that pattern matching always + /// follows `PartialEq` semantics, so that trait bound will become a requirement for + /// matching on constants. + pub CONST_PATTERNS_WITHOUT_PARTIAL_EQ, + Warn, + "constant in pattern does not implement `PartialEq`", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #116122 ", + }; +} + declare_lint! { /// The `ambiguous_associated_items` lint detects ambiguity between /// [associated items] and [enum variants]. @@ -2348,6 +2415,7 @@ declare_lint! { Deny, "ambiguous associated items", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #57644 ", }; } @@ -2389,6 +2457,7 @@ declare_lint! { Deny, "a feature gate that doesn't break dependent crates", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #64266 ", }; } @@ -2617,8 +2686,8 @@ declare_lint! { Deny, "a C-like enum implementing Drop is cast", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #73333 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -2747,6 +2816,7 @@ declare_lint! { Warn, "detects a generic constant is used in a type without a emitting a warning", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #76200 ", }; } @@ -2805,6 +2875,7 @@ declare_lint! { Warn, "uninhabited static", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #74840 ", }; } @@ -2975,8 +3046,8 @@ declare_lint! { Warn, "trailing semicolon in macro body used as expression", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #79813 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -3022,6 +3093,7 @@ declare_lint! { Warn, "detects derive helper attributes that are used before they are introduced", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #79202 ", }; } @@ -3090,6 +3162,7 @@ declare_lint! { Deny, "detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #91632 ", }; } @@ -3181,6 +3254,7 @@ declare_lint! { Warn, "transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #78586 ", }; } @@ -3231,6 +3305,7 @@ declare_lint! { Warn, "unstable syntax can change at any point in the future, causing a hard error!", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #65860 ", }; } @@ -3333,6 +3408,7 @@ declare_lint_pass! { CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, + CONST_PATTERNS_WITHOUT_PARTIAL_EQ, DEAD_CODE, DEPRECATED, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, @@ -3662,6 +3738,7 @@ declare_lint! { Warn, "detects invalid `#[doc(...)]` attributes", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #82730 ", }; } @@ -3708,8 +3785,8 @@ declare_lint! { Deny, "detects usage of old versions of certain proc-macro crates", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #83125 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -3747,8 +3824,8 @@ declare_lint! { Allow, "detects usage of old versions of or-patterns", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + reference: "", }; } @@ -3796,8 +3873,8 @@ declare_lint! { "detects the usage of trait methods which are ambiguous with traits added to the \ prelude in future editions", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + reference: "", }; } @@ -3833,8 +3910,8 @@ declare_lint! { Allow, "identifiers that will be parsed as a prefix in Rust 2021", @future_incompatible = FutureIncompatibleInfo { - reference: "", reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + reference: "", }; crate_level_only } @@ -3881,6 +3958,7 @@ declare_lint! { Warn, "use of unsupported calling convention", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #87678 ", }; } @@ -4221,8 +4299,8 @@ declare_lint! { Deny, "impl method assumes more implied bounds than its corresponding trait method", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #105572 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -4253,8 +4331,8 @@ declare_lint! { Warn, "`[u8]` or `str` used in a packed struct with `derive`", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #107457 ", - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; report_in_external_macro } @@ -4415,6 +4493,7 @@ declare_lint! { "impls that are not considered to overlap may be considered to \ overlap in the future", @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #114040 ", }; } @@ -4483,7 +4562,7 @@ declare_lint! { Warn, "detects certain glob imports that require reporting an ambiguity error", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseError, + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #114095 ", }; } @@ -4568,7 +4647,7 @@ declare_lint! { Warn, "elided lifetimes cannot be used in associated constants in impls", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseError, + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, reference: "issue #115010 ", }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index ef2f794047711..7ba589c3b5a39 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -347,12 +347,18 @@ pub struct FutureIncompatibleInfo { /// The reason for future incompatibility #[derive(Copy, Clone, Debug)] pub enum FutureIncompatibilityReason { - /// This will be an error in a future release - /// for all editions - FutureReleaseError, + /// This will be an error in a future release for all editions + /// + /// This will *not* show up in cargo's future breakage report. + /// The warning will hence only be seen in local crates, not in dependencies. + FutureReleaseErrorDontReportInDeps, /// This will be an error in a future release, and /// Cargo should create a report even for dependencies - FutureReleaseErrorReportNow, + /// + /// This is the *only* reason that will make future incompatibility warnings show up in cargo's + /// reports. All other future incompatibility warnings are not visible when they occur in a + /// dependency. + FutureReleaseErrorReportInDeps, /// Code that changes meaning in some way in a /// future release. FutureReleaseSemanticsChange, @@ -380,7 +386,7 @@ impl FutureIncompatibleInfo { pub const fn default_fields_for_macro() -> Self { FutureIncompatibleInfo { reference: "", - reason: FutureIncompatibilityReason::FutureReleaseError, + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, explain_reason: true, } } @@ -718,7 +724,10 @@ macro_rules! declare_lint { ); ($(#[$attr:meta])* $vis: vis $NAME: ident, $Level: ident, $desc: expr, $(@feature_gate = $gate:expr;)? - $(@future_incompatible = FutureIncompatibleInfo { $($field:ident : $val:expr),* $(,)* }; )? + $(@future_incompatible = FutureIncompatibleInfo { + reason: $reason:expr, + $($field:ident : $val:expr),* $(,)* + }; )? $(@edition $lint_edition:ident => $edition_level:ident;)? $($v:ident),*) => ( $(#[$attr])* @@ -730,6 +739,7 @@ macro_rules! declare_lint { $($v: true,)* $(feature_gate: Some($gate),)? $(future_incompatible: Some($crate::FutureIncompatibleInfo { + reason: $reason, $($field: $val,)* ..$crate::FutureIncompatibleInfo::default_fields_for_macro() }),)? @@ -775,16 +785,7 @@ macro_rules! declare_tool_lint { ); } -/// Declares a static `LintArray` and return it as an expression. -#[macro_export] -macro_rules! lint_array { - ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) }; - ($( $lint:expr ),*) => {{ - vec![$($lint),*] - }} -} - -pub type LintArray = Vec<&'static Lint>; +pub type LintVec = Vec<&'static Lint>; pub trait LintPass { fn name(&self) -> &'static str; @@ -798,7 +799,7 @@ macro_rules! impl_lint_pass { fn name(&self) -> &'static str { stringify!($ty) } } impl $ty { - pub fn get_lints() -> $crate::LintArray { $crate::lint_array!($($lint),*) } + pub fn get_lints() -> $crate::LintVec { vec![$($lint),*] } } }; } diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 34556df3c6d79..3880f25a9ba9d 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -3,10 +3,6 @@ name = "rustc_llvm" version = "0.0.0" edition = "2021" -[features] -static-libstdcpp = [] -emscripten = [] - [dependencies] libc = "0.2.73" diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 461b5290e69d1..31565db1b7929 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -416,6 +416,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool RelaxELFRelocations, bool UseInitArray, const char *SplitDwarfFile, + const char *OutputObjFile, const char *DebugInfoCompression, bool ForceEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { @@ -448,6 +449,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( if (SplitDwarfFile) { Options.MCOptions.SplitDwarfFile = SplitDwarfFile; } + if (OutputObjFile) { + Options.ObjectFilenameForDebug = OutputObjFile; + } #if LLVM_VERSION_GE(16, 0) if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { Options.CompressDebugSections = DebugCompressionType::Zlib; @@ -791,6 +795,20 @@ LLVMRustOptimize( CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; + if (LLVMPluginsLen) { + auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); + SmallVector Plugins; + PluginsStr.split(Plugins, ',', -1, false); + for (auto PluginPath: Plugins) { + auto Plugin = PassPlugin::Load(PluginPath.str()); + if (!Plugin) { + LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); + return LLVMRustResult::Failure; + } + Plugin->registerPassBuilderCallbacks(PB); + } + } + FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); Triple TargetTriple(TheModule->getTargetTriple()); @@ -914,20 +932,6 @@ LLVMRustOptimize( } } - if (LLVMPluginsLen) { - auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); - SmallVector Plugins; - PluginsStr.split(Plugins, ',', -1, false); - for (auto PluginPath: Plugins) { - auto Plugin = PassPlugin::Load(PluginPath.str()); - if (!Plugin) { - LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); - return LLVMRustResult::Failure; - } - Plugin->registerPassBuilderCallbacks(PB); - } - } - ModulePassManager MPM; bool NeedThinLTOBufferPasses = UseThinLTOBuffers; if (!NoPrepopulatePasses) { diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e7b80c64184bf..3e43bcb3b8f6d 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -23,10 +23,10 @@ //! } //! ``` //! -//! Now `LOG=debug cargo run` will run your minimal main.rs and show +//! Now `LOG=debug cargo +nightly run` will run your minimal main.rs and show //! rustc's debug logging. In a workflow like this, one might also add //! `std::env::set_var("LOG", "debug")` to the top of main so that `cargo -//! run` by itself is sufficient to get logs. +//! +nightly run` by itself is sufficient to get logs. //! //! The reason rustc_log is a tiny separate crate, as opposed to exposing the //! same things in rustc_driver only, is to enable the above workflow. If you diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 69221475356d7..14bbe65d5f1fc 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; use rustc_expand::base::SyntaxExtension; +use rustc_fs_util::try_canonicalize; use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::IndexVec; @@ -31,7 +32,7 @@ use std::error::Error; use std::ops::Fn; use std::path::Path; use std::time::Duration; -use std::{cmp, env, iter}; +use std::{cmp, iter}; pub struct CStore { metadata_loader: Box, @@ -677,7 +678,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. - let path = env::current_dir().unwrap().join(path); + let path = try_canonicalize(path).unwrap(); let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?; let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 99fef84931e66..fa77b36c4c556 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -26,7 +26,7 @@ extern crate rustc_middle; #[macro_use] extern crate tracing; -pub use rmeta::{provide, provide_extern}; +pub use rmeta::provide; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a57bff3730d51..b189e79df5646 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -24,7 +24,6 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::GeneratorDiagnosticData; use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::{Decodable, Decoder}; @@ -44,7 +43,6 @@ use std::sync::atomic::Ordering; use std::{io, iter, mem}; pub(super) use cstore_impl::provide; -pub use cstore_impl::provide_extern; use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; @@ -1751,24 +1749,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .clone() } - fn get_generator_diagnostic_data( - self, - tcx: TyCtxt<'tcx>, - id: DefIndex, - ) -> Option> { - self.root - .tables - .generator_diagnostic_data - .get(self, id) - .map(|param| param.decode((self, tcx))) - .map(|generator_data| GeneratorDiagnosticData { - generator_interior_types: generator_data.generator_interior_types, - hir_owner: generator_data.hir_owner, - nodes_types: generator_data.nodes_types, - adjustments: generator_data.adjustments, - }) - } - fn get_attr_flags(self, index: DefIndex) -> AttrFlags { self.root.tables.attr_flags.get(self, index) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f964a8c76c06b..f27eee0d79a53 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -14,10 +14,11 @@ use rustc_middle::arena::ArenaAllocatable; use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; +use rustc_middle::query::ExternProviders; use rustc_middle::query::LocalCrate; -use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::util::Providers; use rustc_session::cstore::CrateStore; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; @@ -126,8 +127,8 @@ macro_rules! provide_one { // External query providers call `crate_hash` in order to register a dependency // on the crate metadata. The exception is `crate_hash` itself, which obviously // doesn't need to do this (and can't, as it would cause a query cycle). - use rustc_middle::dep_graph::DepKind; - if DepKind::$name != DepKind::crate_hash && $tcx.dep_graph.is_fully_enabled() { + use rustc_middle::dep_graph::dep_kinds; + if dep_kinds::$name != dep_kinds::crate_hash && $tcx.dep_graph.is_fully_enabled() { $tcx.ensure().crate_hash($def_id.krate); } @@ -147,7 +148,7 @@ macro_rules! provide_one { macro_rules! provide { ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $($name:ident => { $($compute:tt)* })*) => { - pub fn provide_extern(providers: &mut ExternProviders) { + fn provide_extern(providers: &mut ExternProviders) { $(provide_one! { $tcx, $def_id, $other, $cdata, $name => { $($compute)* } })* @@ -209,6 +210,7 @@ provide! { tcx, def_id, other, cdata, inferred_outlives_of => { table_defaulted_array } super_predicates_of => { table } type_of => { table } + type_alias_is_lazy => { cdata.root.tables.type_alias_is_lazy.get(cdata, def_id.index) } variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } @@ -373,7 +375,6 @@ provide! { tcx, def_id, other, cdata, crate_extern_paths => { cdata.source().paths().cloned().collect() } expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } - generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) } is_doc_hidden => { cdata.get_attr_flags(def_id.index).contains(AttrFlags::IS_DOC_HIDDEN) } doc_link_resolutions => { tcx.arena.alloc(cdata.get_doc_link_resolutions(def_id.index)) } doc_link_traits_in_scope => { @@ -385,7 +386,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // FIXME(#44234) - almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in // resolve! Does this work? Unsure! That's what the issue is about - *providers = Providers { + providers.queries = rustc_middle::query::Providers { allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(), alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(), is_private_dep: |_tcx, LocalCrate| false, @@ -513,8 +514,9 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.untracked().cstore.freeze(); tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum)) }, - ..*providers + ..providers.queries }; + provide_extern(&mut providers.extern_queries); } impl CStore { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index cc7ae932e1162..a4ba943275e4c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -31,7 +31,6 @@ use rustc_middle::query::Providers; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; -use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt}; use rustc_middle::util::common::to_readable_str; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; @@ -827,7 +826,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -862,7 +861,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -903,7 +902,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Variant | DefKind::Trait | DefKind::Impl { .. } => true, - DefKind::TyAlias { .. } + DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -938,7 +937,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -982,7 +981,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::Fn | DefKind::ForeignMod - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Enum | DefKind::Union @@ -1092,9 +1091,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Closure | DefKind::Generator | DefKind::ExternCrate => false, - DefKind::TyAlias { lazy } => { - lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() - } + DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } @@ -1105,7 +1102,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -1145,7 +1142,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Fn | DefKind::Const | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } | DefKind::AssocFn @@ -1205,7 +1202,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::Static(..) | DefKind::Ctor(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1246,7 +1243,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::AnonConst | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } | DefKind::ForeignTy @@ -1279,7 +1276,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::Fn | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1439,7 +1436,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if let DefKind::Generator = def_kind { - self.encode_info_for_generator(local_id); + let data = self.tcx.generator_kind(def_id).unwrap(); + record!(self.tables.generator_kind[def_id] <- data); } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { self.encode_info_for_adt(local_id); @@ -1450,6 +1448,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Macro(_) = def_kind { self.encode_info_for_macro(local_id); } + if let DefKind::TyAlias = def_kind { + self.tables + .type_alias_is_lazy + .set(def_id.index, self.tcx.type_alias_is_lazy(def_id)); + } if let DefKind::OpaqueTy = def_kind { self.encode_explicit_item_bounds(def_id); self.tables @@ -1612,8 +1615,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); - if tcx.sess.opts.unstable_opts.drop_tracking_mir - && let DefKind::Generator = self.tcx.def_kind(def_id) + if let DefKind::Generator = self.tcx.def_kind(def_id) && let Some(witnesses) = tcx.mir_generator_witnesses(def_id) { record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses); @@ -1640,6 +1642,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); + if let DefKind::Generator = self.tcx.def_kind(def_id) + && let Some(witnesses) = tcx.mir_generator_witnesses(def_id) + { + record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses); + } + let instance = ty::InstanceDef::Item(def_id.to_def_id()); let unused = tcx.unused_generic_params(instance); self.tables.unused_generic_params.set(def_id.local_def_index, unused); @@ -1712,15 +1720,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } - #[instrument(level = "debug", skip(self))] - fn encode_info_for_generator(&mut self, def_id: LocalDefId) { - let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id); - let data = self.tcx.generator_kind(def_id).unwrap(); - let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data(); - record!(self.tables.generator_kind[def_id.to_def_id()] <- data); - record!(self.tables.generator_diagnostic_data[def_id.to_def_id()] <- generator_diagnostic_data); - } - fn encode_native_libraries(&mut self) -> LazyArray { empty_proc_macro!(self); let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 71269779d4239..42764af52c43f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -21,10 +21,10 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; -use rustc_middle::query::Providers; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams}; -use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; +use rustc_middle::ty::{DeducedParamAttrs, ParameterizedOverTcx, TyCtxt}; +use rustc_middle::util::Providers; use rustc_serialize::opaque::FileEncoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; @@ -38,7 +38,6 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; use std::num::NonZeroUsize; -pub use decoder::provide_extern; use decoder::DecodeContext; pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; use encoder::EncodeContext; @@ -384,6 +383,7 @@ define_tables! { is_intrinsic: Table, is_macro_rules: Table, is_type_alias_impl_trait: Table, + type_alias_is_lazy: Table, attr_flags: Table, def_path_hashes: Table, explicit_item_bounds: Table, Span)>>, @@ -439,7 +439,7 @@ define_tables! { coerce_unsized_info: Table>, mir_const_qualif: Table>, rendered_const: Table>, - asyncness: Table, + asyncness: Table, fn_arg_names: Table>, generator_kind: Table>, trait_def: Table>, @@ -453,7 +453,6 @@ define_tables! { // definitions from any given crate. def_keys: Table>, proc_macro_quoted_spans: Table>, - generator_diagnostic_data: Table>>, variant_data: Table>, assoc_container: Table, macro_definition: Table>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 35987072ed6bb..bb1320942b077 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -145,8 +145,7 @@ fixed_size_enum! { ( Enum ) ( Variant ) ( Trait ) - ( TyAlias { lazy: false } ) - ( TyAlias { lazy: true } ) + ( TyAlias ) ( ForeignTy ) ( TraitAlias ) ( AssocTy ) @@ -205,9 +204,9 @@ fixed_size_enum! { } fixed_size_enum! { - hir::IsAsync { - ( NotAsync ) - ( Async ) + ty::Asyncness { + ( Yes ) + ( No ) } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 952c796f52e76..1d573a746b918 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -8,7 +8,7 @@ macro_rules! arena_types { ($macro:path) => ( $macro!([ - [] layout: rustc_target::abi::LayoutS, + [] layout: rustc_target::abi::LayoutS, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // AdtDef are interned and compared by address [decode] adt_def: rustc_middle::ty::AdtDefData, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 78a0f82db132a..39d82c489d53f 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -65,9 +65,9 @@ use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; -use std::hash::Hash; -pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; +pub use rustc_query_system::dep_graph::dep_node::DepKind; +pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams}; macro_rules! define_dep_nodes { ( @@ -84,55 +84,39 @@ macro_rules! define_dep_nodes { // encoding. The derived Encodable/Decodable uses leb128 encoding which is // dense when only considering this enum. But DepKind is encoded in a larger // struct, and there we can take advantage of the unused bits in the u16. - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[allow(non_camel_case_types)] - #[repr(u16)] - pub enum DepKind { + #[repr(u16)] // Must be kept in sync with the inner type of `DepKind`. + enum DepKindDefs { $( $( #[$attr] )* $variant),* } - impl DepKind { - // This const implements two things: A bounds check so that we can decode - // a DepKind from a u16 with just one check, and a const check that the - // discriminants of the variants have been assigned consecutively from 0 - // so that just the one comparison suffices to check that the u16 can be - // transmuted to a DepKind. - pub const VARIANTS: u16 = { - let deps: &[DepKind] = &[$(DepKind::$variant,)*]; - let mut i = 0; - while i < deps.len() { - if i as u16 != deps[i] as u16 { - panic!(); - } - i += 1; - } - deps.len() as u16 - }; - } + #[allow(non_upper_case_globals)] + pub mod dep_kinds { + use super::*; - impl rustc_serialize::Encodable for DepKind { - #[inline] - fn encode(&self, s: &mut S) { - s.emit_u16(*self as u16); - } + $( + // The `as u16` cast must be kept in sync with the inner type of `DepKind`. + pub const $variant: DepKind = DepKind::new(DepKindDefs::$variant as u16); + )* } - impl rustc_serialize::Decodable for DepKind { - #[inline] - fn decode(d: &mut D) -> DepKind { - let discrim = d.read_u16(); - assert!(discrim < DepKind::VARIANTS); - // SAFETY: DepKind::VARIANTS checks that the discriminant values permit - // this one check to soundly guard the transmute. - unsafe { - std::mem::transmute::(discrim) + // This checks that the discriminants of the variants have been assigned consecutively + // from 0 so that they can be used as a dense index. + pub const DEP_KIND_VARIANTS: u16 = { + let deps = &[$(dep_kinds::$variant,)*]; + let mut i = 0; + while i < deps.len() { + if i != deps[i].as_usize() { + panic!(); } + i += 1; } - } + deps.len() as u16 + }; pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { - $(stringify!($variant) => Ok(DepKind::$variant),)* + $(stringify!($variant) => Ok(dep_kinds::$variant),)* _ => Err(()), } } @@ -158,12 +142,10 @@ rustc_query_append!(define_dep_nodes![ [] fn CompileMonoItem() -> (), ]); -static_assert_size!(DepKind, 2); - // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. // Be very careful changing this type signature! pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { - DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name) + DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name) } // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. @@ -172,20 +154,9 @@ pub(crate) fn make_compile_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, ) -> DepNode { - DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) + DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item) } -pub type DepNode = rustc_query_system::dep_graph::DepNode; - -// We keep a lot of `DepNode`s in memory during compilation. It's not -// required that their size stay the same, but we don't want to change -// it inadvertently. This assert just ensures we're aware of any change. -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 18); - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -static_assert_size!(DepNode, 24); - pub trait DepNodeExt: Sized { /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 87436f9eeed86..76ef62f9f2728 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -6,49 +6,24 @@ use rustc_session::Session; #[macro_use] mod dep_node; +pub use rustc_query_system::dep_graph::debug::EdgeFilter; pub use rustc_query_system::dep_graph::{ - debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex, - SerializedDepNodeIndex, WorkProduct, WorkProductId, WorkProductMap, + debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeColor, DepNodeIndex, Deps, + SerializedDepGraph, SerializedDepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, WorkProductId, + WorkProductMap, }; -pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; +pub use dep_node::{dep_kinds, label_strs, DepKind, DepNode, DepNodeExt}; pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; -pub type DepGraph = rustc_query_system::dep_graph::DepGraph; +pub type DepGraph = rustc_query_system::dep_graph::DepGraph; -pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; -pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; -pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; -pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; -pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct>; -impl rustc_query_system::dep_graph::DepKind for DepKind { - const NULL: Self = DepKind::Null; - const RED: Self = DepKind::Red; - const MAX: u16 = DepKind::VARIANTS - 1; - - fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}(", node.kind)?; - - ty::tls::with_opt(|opt_tcx| { - if let Some(tcx) = opt_tcx { - if let Some(def_id) = node.extract_def_id(tcx) { - write!(f, "{}", tcx.def_path_debug_str(def_id))?; - } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*node) { - write!(f, "{s}")?; - } else { - write!(f, "{}", node.hash)?; - } - } else { - write!(f, "{}", node.hash)?; - } - Ok(()) - })?; - - write!(f, ")") - } +#[derive(Clone)] +pub struct DepsType; +impl Deps for DepsType { fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R where OP: FnOnce() -> R, @@ -70,24 +45,13 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { }) } - #[track_caller] - #[inline] - fn from_u16(u: u16) -> Self { - if u > Self::MAX { - panic!("Invalid DepKind {u}"); - } - // SAFETY: See comment on DepKind::VARIANTS - unsafe { std::mem::transmute(u) } - } - - #[inline] - fn to_u16(self) -> u16 { - self as u16 - } + const DEP_KIND_NULL: DepKind = dep_kinds::Null; + const DEP_KIND_RED: DepKind = dep_kinds::Red; + const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } impl<'tcx> DepContext for TyCtxt<'tcx> { - type DepKind = DepKind; + type Deps = DepsType; #[inline] fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { @@ -111,6 +75,6 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { #[inline] fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> { - &self.query_kinds[dk as usize] + &self.query_kinds[dk.as_usize()] } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index f67f8015c0409..77643715fff5e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -196,9 +196,7 @@ impl<'hir> Map<'hir> { ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::TyAlias(..) => { - DefKind::TyAlias { lazy: self.tcx.features().lazy_type_alias } - } + ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, ItemKind::Union(..) => DefKind::Union, @@ -442,9 +440,10 @@ impl<'hir> Map<'hir> { /// Panics if `LocalDefId` does not have an associated body. pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind { match self.tcx.def_kind(def_id) { - DefKind::Const | DefKind::AssocConst | DefKind::InlineConst | DefKind::AnonConst => { - BodyOwnerKind::Const + DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { + BodyOwnerKind::Const { inline: false } } + DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure | DefKind::Generator => BodyOwnerKind::Closure, DefKind::Static(mt) => BodyOwnerKind::Static(mt), @@ -461,7 +460,7 @@ impl<'hir> Map<'hir> { /// just that it has to be checked as if it were. pub fn body_const_context(self, def_id: LocalDefId) -> Option { let ccx = match self.body_owner_kind(def_id) { - BodyOwnerKind::Const => ConstContext::Const, + BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, BodyOwnerKind::Static(mt) => ConstContext::Static(mt), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None, @@ -971,12 +970,15 @@ impl<'hir> Map<'hir> { // SyntaxContext of the visibility. sig.span.find_ancestor_in_same_ctxt(*outer_span).unwrap_or(*outer_span) } + // Impls, including their where clauses. + Node::Item(Item { + kind: ItemKind::Impl(Impl { generics, .. }), + span: outer_span, + .. + }) => until_within(*outer_span, generics.where_clause_span), // Constants and Statics. Node::Item(Item { - kind: - ItemKind::Const(ty, ..) - | ItemKind::Static(ty, ..) - | ItemKind::Impl(Impl { self_ty: ty, .. }), + kind: ItemKind::Const(ty, ..) | ItemKind::Static(ty, ..), span: outer_span, .. }) diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs new file mode 100644 index 0000000000000..572751d951189 --- /dev/null +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -0,0 +1,70 @@ +//! "Hooks" provide a way for `tcx` functionality to be provided by some downstream crate without +//! everything in rustc having to depend on that crate. This is somewhat similar to queries, but +//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are +//! just plain function pointers without any of the query magic. + +use crate::mir; +use crate::query::TyCtxtAt; +use crate::ty::{Ty, TyCtxt}; +use rustc_span::DUMMY_SP; + +macro_rules! declare_hooks { + ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => { + + impl<'tcx> TyCtxt<'tcx> { + $( + $(#[$attr])* + #[inline(always)] + #[must_use] + pub fn $name(self, $($arg: $K,)*) -> $V + { + self.at(DUMMY_SP).$name($($arg,)*) + } + )* + } + + impl<'tcx> TyCtxtAt<'tcx> { + $( + $(#[$attr])* + #[inline(always)] + #[must_use] + #[instrument(level = "debug", skip(self), ret)] + pub fn $name(self, $($arg: $K,)*) -> $V + { + (self.tcx.hooks.$name)(self, $($arg,)*) + } + )* + } + + pub struct Providers { + $(pub $name: for<'tcx> fn( + TyCtxtAt<'tcx>, + $($arg: $K,)* + ) -> $V,)* + } + + impl Default for Providers { + fn default() -> Self { + Providers { + $($name: |_, $($arg,)*| bug!( + "`tcx.{}{:?}` cannot be called as `{}` was never assigned to a provider function.\n", + stringify!($name), + ($($arg,)*), + stringify!($name), + ),)* + } + } + } + + impl Copy for Providers {} + impl Clone for Providers { + fn clone(&self) -> Self { *self } + } + }; +} + +declare_hooks! { + /// Tries to destructure an `mir::Const` ADT or array into its variant index + /// and its field values. This should only be used for pretty printing. + hook try_destructure_mir_constant_for_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option>; +} diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 2f2597d6b2232..41beca072bfea 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -455,7 +455,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { let br = ty::BoundRegion { var: ty::BoundVar::from_usize(i), - kind: ty::BrAnon(None), + kind: ty::BrAnon, }; ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 50b69181d67ef..fe4fc3761b377 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -89,6 +89,7 @@ mod macros; pub mod arena; pub mod error; pub mod hir; +pub mod hooks; pub mod infer; pub mod lint; pub mod metadata; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 037f84f476fb7..59849e8eb407c 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -314,7 +314,10 @@ pub fn struct_lint_level( // Default allow lints trigger too often for testing. sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow, |incompat| { - matches!(incompat.reason, FutureIncompatibilityReason::FutureReleaseErrorReportNow) + matches!( + incompat.reason, + FutureIncompatibilityReason::FutureReleaseErrorReportInDeps + ) }, ); @@ -404,8 +407,8 @@ pub fn struct_lint_level( if let Some(future_incompatible) = future_incompatible { let explanation = match future_incompatible.reason { - FutureIncompatibilityReason::FutureReleaseError - | FutureIncompatibilityReason::FutureReleaseErrorReportNow => { + FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps + | FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => { "this was previously accepted by the compiler but is being phased out; \ it will become a hard error in a future release!" .to_owned() diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 908ab8b613e88..c66f64dde3291 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -448,14 +448,14 @@ impl<'tcx> TyCtxt<'tcx> { debug!("stability: skipping span={:?} since it is internal", span); return EvalResult::Allow; } - if self.features().active(feature) { + if self.features().declared(feature) { return EvalResult::Allow; } // If this item was previously part of a now-stabilized feature which is still // active (i.e. the user hasn't removed the attribute for the stabilized feature // yet) then allow use of this item. - if let Some(implied_by) = implied_by && self.features().active(implied_by) { + if let Some(implied_by) = implied_by && self.features().declared(implied_by) { return EvalResult::Allow; } @@ -532,7 +532,7 @@ impl<'tcx> TyCtxt<'tcx> { debug!("body stability: skipping span={:?} since it is internal", span); return EvalResult::Allow; } - if self.features().active(feature) { + if self.features().declared(feature) { return EvalResult::Allow; } diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index cd770c395e4d3..3ecd5b9cd3456 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -63,11 +63,14 @@ impl<'tcx> BasicBlocks<'tcx> { } /// Returns basic blocks in a reverse postorder. + /// + /// See [`traversal::reverse_postorder`]'s docs to learn what is preorder traversal. + /// + /// [`traversal::reverse_postorder`]: crate::mir::traversal::reverse_postorder #[inline] pub fn reverse_postorder(&self) -> &[BasicBlock] { self.cache.reverse_postorder.get_or_init(|| { - let mut rpo: Vec<_> = - Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect(); + let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect(); rpo.reverse(); rpo }) diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 0115b1dcb3ec0..4e429f316e806 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -6,13 +6,11 @@ use rustc_hir::{self as hir}; use rustc_span::Span; use rustc_target::abi::{HasDataLayout, Size}; -use crate::mir::interpret::{ - alloc_range, AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar, -}; +use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar}; use crate::mir::{pretty_print_const_value, Promoted}; +use crate::ty::ScalarInt; use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt}; use crate::ty::{GenericArgs, GenericArgsRef}; -use crate::ty::{ScalarInt, UserTypeAnnotationIndex}; /////////////////////////////////////////////////////////////////////////// /// Evaluated Constants @@ -178,29 +176,10 @@ impl<'tcx> ConstValue<'tcx> { /////////////////////////////////////////////////////////////////////////// /// Constants -/// -/// Two constants are equal if they are the same constant. Note that -/// this does not necessarily mean that they are `==` in Rust. In -/// particular, one must be wary of `NaN`! - -#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct Constant<'tcx> { - pub span: Span, - - /// Optional user-given type: for something like - /// `collect::>`, this would be present and would - /// indicate that `Vec<_>` was explicitly specified. - /// - /// Needed for NLL to impose user-given type constraints. - pub user_ty: Option, - - pub literal: ConstantKind<'tcx>, -} #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)] #[derive(TypeFoldable, TypeVisitable)] -pub enum ConstantKind<'tcx> { +pub enum Const<'tcx> { /// This constant came from the type system. /// /// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`; @@ -221,46 +200,27 @@ pub enum ConstantKind<'tcx> { Val(ConstValue<'tcx>, Ty<'tcx>), } -impl<'tcx> Constant<'tcx> { - pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { - match self.literal.try_to_scalar() { - Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { - GlobalAlloc::Static(def_id) => { - assert!(!tcx.is_thread_local_static(def_id)); - Some(def_id) - } - _ => None, - }, - _ => None, - } - } - #[inline] - pub fn ty(&self) -> Ty<'tcx> { - self.literal.ty() - } -} - -impl<'tcx> ConstantKind<'tcx> { +impl<'tcx> Const<'tcx> { #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { - ConstantKind::Ty(c) => c.ty(), - ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty, + Const::Ty(c) => c.ty(), + Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty, } } #[inline] pub fn try_to_scalar(self) -> Option { match self { - ConstantKind::Ty(c) => match c.kind() { - ty::ConstKind::Value(valtree) => match valtree { - ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)), - ty::ValTree::Branch(_) => None, - }, + Const::Ty(c) => match c.kind() { + ty::ConstKind::Value(valtree) if c.ty().is_primitive() => { + // A valtree of a type where leaves directly represent the scalar const value. + Some(valtree.unwrap_leaf().into()) + } _ => None, }, - ConstantKind::Val(val, _) => val.try_to_scalar(), - ConstantKind::Unevaluated(..) => None, + Const::Val(val, _) => val.try_to_scalar(), + Const::Unevaluated(..) => None, } } @@ -287,17 +247,17 @@ impl<'tcx> ConstantKind<'tcx> { span: Option, ) -> Result, ErrorHandled> { match self { - ConstantKind::Ty(c) => { + Const::Ty(c) => { // We want to consistently have a "clean" value for type system constants (i.e., no // data hidden in the padding), so we always go through a valtree here. let val = c.eval(tcx, param_env, span)?; Ok(tcx.valtree_to_const_val((self.ty(), val))) } - ConstantKind::Unevaluated(uneval, _) => { + Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` tcx.const_eval_resolve(param_env, uneval, span) } - ConstantKind::Val(val, _) => Ok(val), + Const::Val(val, _) => Ok(val), } } @@ -319,7 +279,16 @@ impl<'tcx> ConstantKind<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option { - self.eval(tcx, param_env, None).ok()?.try_to_scalar() + match self { + Const::Ty(c) if c.ty().is_primitive() => { + // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that + // are valtree leaves, and *not* on references. (References should return the + // pointer here, which valtrees don't represent.) + let val = c.eval(tcx, param_env, None).ok()?; + Some(val.unwrap_leaf().into()) + } + _ => self.eval(tcx, param_env, None).ok()?.try_to_scalar(), + } } #[inline] @@ -332,23 +301,18 @@ impl<'tcx> ConstantKind<'tcx> { } #[inline] - pub fn try_eval_bits( - &self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - ) -> Option { + pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { let int = self.try_eval_scalar_int(tcx, param_env)?; - assert_eq!(self.ty(), ty); - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = + tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; int.to_bits(size).ok() } /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. #[inline] - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env, ty) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } #[inline] @@ -416,7 +380,7 @@ impl<'tcx> ConstantKind<'tcx> { Self::Val(val, ty) } - /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly + /// Literals are converted to `Const::Val`, const generic parameters are eagerly /// converted to a constant, everything else becomes `Unevaluated`. #[instrument(skip(tcx), level = "debug", ret)] pub fn from_anon_const( @@ -552,29 +516,13 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -impl<'tcx> Debug for Constant<'tcx> { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - write!(fmt, "{self}") - } -} - -impl<'tcx> Display for Constant<'tcx> { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - match self.ty().kind() { - ty::FnDef(..) => {} - _ => write!(fmt, "const ")?, - } - Display::fmt(&self.literal, fmt) - } -} - -impl<'tcx> Display for ConstantKind<'tcx> { +impl<'tcx> Display for Const<'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), + Const::Ty(c) => pretty_print_const(c, fmt, true), + Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt), // FIXME(valtrees): Correctly print mir constants. - ConstantKind::Unevaluated(..) => { + Const::Unevaluated(..) => { fmt.write_str("_")?; Ok(()) } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 1efb54bdb0872..a6d6f6f5df4b3 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -18,11 +18,6 @@ rustc_index::newtype_index! { impl CounterId { pub const START: Self = Self::from_u32(0); - - #[inline(always)] - pub fn next_id(self) -> Self { - Self::from_u32(self.as_u32() + 1) - } } rustc_index::newtype_index! { @@ -38,21 +33,6 @@ rustc_index::newtype_index! { impl ExpressionId { pub const START: Self = Self::from_u32(0); - - #[inline(always)] - pub fn next_id(self) -> Self { - Self::from_u32(self.as_u32() + 1) - } -} - -rustc_index::newtype_index! { - /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their - /// array position in the LLVM coverage map "Expressions" array, which is assembled during the - /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s. - #[derive(HashStable)] - #[max = 0xFFFF_FFFF] - #[debug_format = "MappedExpressionIndex({})"] - pub struct MappedExpressionIndex {} } /// Operand of a coverage-counter expression. diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index bc464aca5f3c0..9de40b3f97459 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -43,21 +43,6 @@ impl ErrorHandled { } } - pub fn emit_err(&self, tcx: TyCtxt<'_>) -> ErrorGuaranteed { - match self { - &ErrorHandled::Reported(err, span) => { - if !err.is_tainted_by_errors && !span.is_dummy() { - tcx.sess.emit_err(error::ErroneousConstant { span }); - } - err.error - } - &ErrorHandled::TooGeneric(span) => tcx.sess.delay_span_bug( - span, - "encountered TooGeneric error when monomorphic data was expected", - ), - } - } - pub fn emit_note(&self, tcx: TyCtxt<'_>) { match self { &ErrorHandled::Reported(err, span) => { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 87180b56baa26..f979f736b1577 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2,7 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html -use crate::mir::interpret::{AllocRange, ConstAllocation, ErrorHandled, Scalar}; +use crate::mir::interpret::{AllocRange, ConstAllocation, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; @@ -318,7 +318,7 @@ pub struct Body<'tcx> { /// Constants that are required to evaluate successfully for this MIR to be well-formed. /// We hold in this field all the constants we are not able to evaluate yet. - pub required_consts: Vec>, + pub required_consts: Vec>, /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check. /// @@ -568,34 +568,6 @@ impl<'tcx> Body<'tcx> { pub fn is_custom_mir(&self) -> bool { self.injection_phase.is_some() } - - /// *Must* be called once the full substitution for this body is known, to ensure that the body - /// is indeed fit for code generation or consumption more generally. - /// - /// Sadly there's no nice way to represent an "arbitrary normalizer", so we take one for - /// constants specifically. (`Option` could be used for that, but the fact - /// that `Instance::args_for_mir_body` is private and instead instance exposes normalization - /// functions makes it seem like exposing the generic args is not the intended strategy.) - /// - /// Also sadly, CTFE doesn't even know whether it runs on MIR that is already polymorphic or still monomorphic, - /// so we cannot just immediately ICE on TooGeneric. - /// - /// Returns Ok(()) if everything went fine, and `Err` if a problem occurred and got reported. - pub fn post_mono_checks( - &self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - normalize_const: impl Fn(ConstantKind<'tcx>) -> Result, ErrorHandled>, - ) -> Result<(), ErrorHandled> { - // For now, the only thing we have to check is is to ensure that all the constants used in - // the body successfully evaluate. - for &const_ in &self.required_consts { - let c = normalize_const(const_.literal)?; - c.eval(tcx, param_env, Some(const_.span))?; - } - - Ok(()) - } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] @@ -830,22 +802,6 @@ pub struct LocalDecl<'tcx> { // FIXME(matthewjasper) Don't store in this in `Body` pub local_info: ClearCrossCrate>>, - /// `true` if this is an internal local. - /// - /// These locals are not based on types in the source code and are only used - /// for a few desugarings at the moment. - /// - /// The generator transformation will sanity check the locals which are live - /// across a suspension point against the type components of the generator - /// which type checking knows are live across a suspension point. We need to - /// flag drop flags to avoid triggering this check as they are introduced - /// outside of type inference. - /// - /// This should be sound because the drop flags are fully algebraic, and - /// therefore don't affect the auto-trait or outlives properties of the - /// generator. - pub internal: bool, - /// The type of this local. pub ty: Ty<'tcx>, @@ -1058,7 +1014,7 @@ impl<'tcx> LocalDecl<'tcx> { self.source_info.span.desugaring_kind().is_some() } - /// Creates a new `LocalDecl` for a temporary: mutable, non-internal. + /// Creates a new `LocalDecl` for a temporary, mutable. #[inline] pub fn new(ty: Ty<'tcx>, span: Span) -> Self { Self::with_source_info(ty, SourceInfo::outermost(span)) @@ -1070,20 +1026,12 @@ impl<'tcx> LocalDecl<'tcx> { LocalDecl { mutability: Mutability::Mut, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)), - internal: false, ty, user_ty: None, source_info, } } - /// Converts `self` into same `LocalDecl` except tagged as internal. - #[inline] - pub fn internal(mut self) -> Self { - self.internal = true; - self - } - /// Converts `self` into same `LocalDecl` except tagged as immutable. #[inline] pub fn immutable(mut self) -> Self { @@ -1096,7 +1044,7 @@ impl<'tcx> LocalDecl<'tcx> { pub enum VarDebugInfoContents<'tcx> { /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`. Place(Place<'tcx>), - Const(Constant<'tcx>), + Const(ConstOperand<'tcx>), } impl<'tcx> Debug for VarDebugInfoContents<'tcx> { @@ -1614,6 +1562,23 @@ impl Location { } } +/// `DefLocation` represents the location of a definition - either an argument or an assignment +/// within MIR body. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum DefLocation { + Argument, + Body(Location), +} + +impl DefLocation { + pub fn dominates(self, location: Location, dominators: &Dominators) -> bool { + match self { + DefLocation::Argument => true, + DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators), + } + } +} + // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index da486c3465a6c..ce2ddec011610 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> { Location { block: bb, statement_index: offset } } - pub fn new_internal_with_info( + pub fn new_local_with_info( &mut self, ty: Ty<'tcx>, span: Span, @@ -135,7 +135,7 @@ impl<'tcx> MirPatch<'tcx> { ) -> Local { let index = self.next_local; self.next_local += 1; - let mut new_decl = LocalDecl::new(ty, span).internal(); + let mut new_decl = LocalDecl::new(ty, span); **new_decl.local_info.as_mut().assert_crate_local() = local_info; self.new_locals.push(new_decl); Local::new(index) @@ -148,13 +148,6 @@ impl<'tcx> MirPatch<'tcx> { Local::new(index) } - pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local { - let index = self.next_local; - self.next_local += 1; - self.new_locals.push(LocalDecl::new(ty, span).internal()); - Local::new(index) - } - pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { let block = BasicBlock::new(self.patch_map.len()); debug!("MirPatch: new_block: {:?}: {:?}", block, data); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 632f159a7a889..c5e3ee575e1a3 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::interpret::{ Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::*; +use rustc_middle::mir::{self, *}; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::Size; @@ -685,10 +685,13 @@ impl Debug for Statement<'_> { AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } - Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => { - write!(fmt, "Coverage::{kind:?} for {rgn:?}") + Coverage(box mir::Coverage { ref kind, ref code_regions }) => { + if code_regions.is_empty() { + write!(fmt, "Coverage::{kind:?}") + } else { + write!(fmt, "Coverage::{kind:?} for {code_regions:?}") + } } - Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), @@ -696,6 +699,17 @@ impl Debug for Statement<'_> { } } +impl Display for NonDivergingIntrinsic<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Assume(op) => write!(f, "assume({op:?})"), + Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => { + write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})") + } + } + } +} + impl<'tcx> Debug for TerminatorKind<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { self.fmt_head(fmt)?; @@ -990,11 +1004,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { let args = tcx.lift(args).unwrap(); - format!("[closure@{}]", tcx.def_path_str_with_args(def_id, args),) + format!("{{closure@{}}}", tcx.def_path_str_with_args(def_id, args),) } else { let span = tcx.def_span(def_id); format!( - "[closure@{}]", + "{{closure@{}}}", tcx.sess.source_map().span_to_diagnostic_string(span) ) }; @@ -1018,7 +1032,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }), AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| { - let name = format!("[generator@{:?}]", tcx.def_span(def_id)); + let name = format!("{{generator@{:?}}}", tcx.def_span(def_id)); let mut struct_fmt = fmt.debug_struct(&name); // FIXME(project-rfc-2229#48): This should be a list of capture names/places @@ -1058,6 +1072,22 @@ impl<'tcx> Debug for Operand<'tcx> { } } +impl<'tcx> Debug for ConstOperand<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + write!(fmt, "{self}") + } +} + +impl<'tcx> Display for ConstOperand<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + match self.ty().kind() { + ty::FnDef(..) => {} + _ => write!(fmt, "const ")?, + } + Display::fmt(&self.const_, fmt) + } +} + impl Debug for Place<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { self.as_ref().fmt(fmt) @@ -1076,6 +1106,7 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> for &elem in projection.iter().rev() { match elem { ProjectionElem::OpaqueCast(_) + | ProjectionElem::Subtype(_) | ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { write!(fmt, "(").unwrap(); @@ -1098,6 +1129,9 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::OpaqueCast(ty) => { write!(fmt, " as {ty})")?; } + ProjectionElem::Subtype(ty) => { + write!(fmt, " as subtype {ty})")?; + } ProjectionElem::Downcast(Some(name), _index) => { write!(fmt, " as {name})")?; } @@ -1119,10 +1153,10 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => { write!(fmt, "[-{offset:?} of {min_length:?}]")?; } - ProjectionElem::Subslice { from, to, from_end: true } if to == 0 => { + ProjectionElem::Subslice { from, to: 0, from_end: true } => { write!(fmt, "[{from:?}:]")?; } - ProjectionElem::Subslice { from, to, from_end: true } if from == 0 => { + ProjectionElem::Subslice { from: 0, to, from_end: true } => { write!(fmt, "[:-{to:?}]")?; } ProjectionElem::Subslice { from, to, from_end: true } => { @@ -1184,10 +1218,10 @@ fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool { } impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { - fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) { - let Constant { span, user_ty, literal } = constant; - if use_verbose(literal.ty(), true) { - self.push("mir::Constant"); + fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) { + let ConstOperand { span, user_ty, const_ } = constant; + if use_verbose(const_.ty(), true) { + self.push("mir::ConstOperand"); self.push(&format!( "+ span: {}", self.tcx.sess.source_map().span_to_embeddable_string(*span) @@ -1209,8 +1243,8 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ValTree::Branch(_) => "Branch(..)".to_string(), }; - let val = match literal { - ConstantKind::Ty(ct) => match ct.kind() { + let val = match const_ { + Const::Ty(ct) => match ct.kind() { ty::ConstKind::Param(p) => format!("ty::Param({p})"), ty::ConstKind::Unevaluated(uv) => { format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) @@ -1222,9 +1256,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Placeholder(_) | ty::ConstKind::Infer(_) | ty::ConstKind::Expr(_) - | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal), + | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", const_), }, - ConstantKind::Unevaluated(uv, _) => { + Const::Unevaluated(uv, _) => { format!( "Unevaluated({}, {:?}, {:?})", self.tcx.def_path_str(uv.def), @@ -1232,13 +1266,13 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { uv.promoted, ) } - ConstantKind::Val(val, ty) => format!("Value({})", fmt_val(*val, *ty)), + Const::Val(val, ty) => format!("Value({})", fmt_val(*val, *ty)), }; // This reflects what `Const` looked liked before `val` was renamed // as `kind`. We print it like this to avoid having to update // expected output in a lot of tests. - self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val)); + self.push(&format!("+ const_: Const {{ ty: {}, val: {} }}", const_.ty(), val)); } } @@ -1312,10 +1346,10 @@ pub fn write_allocations<'tcx>( struct CollectAllocIds(BTreeSet); impl<'tcx> Visitor<'tcx> for CollectAllocIds { - fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) { - match c.literal { - ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {} - ConstantKind::Val(val, _) => { + fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) { + match c.const_ { + Const::Ty(_) | Const::Unevaluated(..) => {} + Const::Val(val, _) => { self.0.extend(alloc_ids_from_const_val(val)); } } @@ -1664,7 +1698,7 @@ fn pretty_print_const_value_tcx<'tcx>( (_, 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_for_diagnostics((ct, ty)) { + 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(..) => { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index c157b7052abb3..c74a9536b6335 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -414,8 +414,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { ty::ReVar(vid) => { - let br = - ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) }; + let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon }; ty::Region::new_late_bound(tcx, depth, br) } _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 25534f4696047..5864acaed7b23 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -1,5 +1,5 @@ /// Functionality for statements, operands, places, and things that appear in them. -use super::*; +use super::{interpret::GlobalAlloc, *}; /////////////////////////////////////////////////////////////////////////// // Statements @@ -57,6 +57,7 @@ impl ProjectionElem { Self::Field(_, _) | Self::Index(_) | Self::OpaqueCast(_) + | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } | Self::Downcast(_, _) => false, @@ -70,6 +71,7 @@ impl ProjectionElem { Self::Deref | Self::Index(_) => false, Self::Field(_, _) | Self::OpaqueCast(_) + | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } | Self::Downcast(_, _) => true, @@ -95,6 +97,7 @@ impl ProjectionElem { | Self::Field(_, _) => true, Self::ConstantIndex { from_end: true, .. } | Self::Index(_) + | Self::Subtype(_) | Self::OpaqueCast(_) | Self::Subslice { .. } => false, } @@ -302,10 +305,10 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Self { let ty = Ty::new_fn_def(tcx, def_id, args); - Operand::Constant(Box::new(Constant { + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, - literal: ConstantKind::Val(ConstValue::ZeroSized, ty), + const_: Const::Val(ConstValue::ZeroSized, ty), })) } @@ -333,10 +336,10 @@ impl<'tcx> Operand<'tcx> { }; scalar_size == type_size }); - Operand::Constant(Box::new(Constant { + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, - literal: ConstantKind::Val(ConstValue::Scalar(val), ty), + const_: Const::Val(ConstValue::Scalar(val), ty), })) } @@ -356,9 +359,9 @@ impl<'tcx> Operand<'tcx> { } } - /// Returns the `Constant` that is the target of this `Operand`, or `None` if this `Operand` is a + /// Returns the `ConstOperand` that is the target of this `Operand`, or `None` if this `Operand` is a /// place. - pub fn constant(&self) -> Option<&Constant<'tcx>> { + pub fn constant(&self) -> Option<&ConstOperand<'tcx>> { match self { Operand::Constant(x) => Some(&**x), Operand::Copy(_) | Operand::Move(_) => None, @@ -370,11 +373,31 @@ impl<'tcx> Operand<'tcx> { /// While this is unlikely in general, it's the normal case of what you'll /// find as the `func` in a [`TerminatorKind::Call`]. pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> { - let const_ty = self.constant()?.literal.ty(); + let const_ty = self.constant()?.const_.ty(); if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None } } } +impl<'tcx> ConstOperand<'tcx> { + pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { + match self.const_.try_to_scalar() { + Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { + GlobalAlloc::Static(def_id) => { + assert!(!tcx.is_thread_local_static(def_id)); + Some(def_id) + } + _ => None, + }, + _ => None, + } + } + + #[inline] + pub fn ty(&self) -> Ty<'tcx> { + self.const_.ty() + } +} + /////////////////////////////////////////////////////////////////////////// /// Rvalues diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f99084d0eb7a5..30fc69caa3bd4 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -3,7 +3,7 @@ //! This is in a dedicated file so that changes to this file can be reviewed more carefully. //! The intention is that this file only contains datatype declarations, no code. -use super::{BasicBlock, Constant, Local, UserTypeProjection}; +use super::{BasicBlock, Const, Local, UserTypeProjection}; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; @@ -139,6 +139,7 @@ pub enum RuntimePhase { /// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::GeneratorDrop`] /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` + /// * [`PlaceElem::OpaqueCast`] /// /// And the following variants are allowed: /// * [`StatementKind::Retag`] @@ -439,17 +440,6 @@ pub enum NonDivergingIntrinsic<'tcx> { CopyNonOverlapping(CopyNonOverlapping<'tcx>), } -impl std::fmt::Display for NonDivergingIntrinsic<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Assume(op) => write!(f, "assume({op:?})"), - Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => { - write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})") - } - } - } -} - /// Describes what kind of retag is to be performed. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] @@ -524,7 +514,7 @@ pub enum FakeReadCause { #[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, - pub code_region: Option, + pub code_regions: Vec, } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -913,10 +903,10 @@ pub enum InlineAsmOperand<'tcx> { out_place: Option>, }, Const { - value: Box>, + value: Box>, }, SymFn { - value: Box>, + value: Box>, }, SymStatic { def_id: DefId, @@ -1006,7 +996,7 @@ pub type AssertMessage<'tcx> = AssertKind>; /// /// [UCG#319]: https://github.com/rust-lang/unsafe-code-guidelines/issues/319 /// -/// Rust currently requires that every place obey those two rules. This is checked by MIRI and taken +/// Rust currently requires that every place obey those two rules. This is checked by Miri and taken /// advantage of by codegen (via `gep inbounds`). That is possibly subject to change. #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Place<'tcx> { @@ -1085,6 +1075,18 @@ pub enum ProjectionElem { /// Like an explicit cast from an opaque type to a concrete type, but without /// requiring an intermediate variable. OpaqueCast(T), + + /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where + /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping + /// explicit during optimizations and codegen. + /// + /// This projection doesn't impact the runtime behavior of the program except for potentially changing + /// some type metadata of the interpreter or codegen backend. + /// + /// This goal is achieved with mir_transform pass `Subtyper`, which runs right after + /// borrowchecker, as we only care about subtyping that can affect trait selection and + /// `TypeId`. + Subtype(T), } /// Alias for projections as they appear in places, where the base is a place @@ -1136,7 +1138,22 @@ pub enum Operand<'tcx> { Move(Place<'tcx>), /// Constants are already semantically values, and remain unchanged. - Constant(Box>), + Constant(Box>), +} + +#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct ConstOperand<'tcx> { + pub span: Span, + + /// Optional user-given type: for something like + /// `collect::>`, this would be present and would + /// indicate that `Vec<_>` was explicitly specified. + /// + /// Needed for NLL to impose user-given type constraints. + pub user_ty: Option, + + pub const_: Const<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -1329,7 +1346,7 @@ pub enum AggregateKind<'tcx> { Generator(DefId, GenericArgsRef<'tcx>, hir::Movability), } -#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum NullOp<'tcx> { /// Returns the size of a value of that type SizeOf, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index f79697936d28c..44ae75e2de701 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -69,7 +69,7 @@ impl<'tcx> PlaceTy<'tcx> { param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem, mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, - mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>, + mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, ) -> PlaceTy<'tcx> where V: ::std::fmt::Debug, @@ -110,7 +110,12 @@ impl<'tcx> PlaceTy<'tcx> { PlaceTy { ty: self.ty, variant_index: Some(index) } } ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)), - ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)), + ProjectionElem::OpaqueCast(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } + ProjectionElem::Subtype(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } }; debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); answer @@ -227,7 +232,7 @@ impl<'tcx> Operand<'tcx> { { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - Operand::Constant(c) => c.literal.ty(), + Operand::Constant(c) => c.const_.ty(), } } } diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index ec16a8470c412..a1ff8410eac4a 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -41,6 +41,12 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { } } +/// Preorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that +/// returns basic blocks in a preorder. +/// +/// See [`Preorder`]'s docs to learn what is preorder traversal. pub fn preorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Preorder<'a, 'tcx> { Preorder::new(body, START_BLOCK) } @@ -178,7 +184,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but // since we've already visited `E`, that child isn't added to the stack. The last // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A] - while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next_back() { + while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) { if self.visited.insert(bb) { if let Some(term) = &self.basic_blocks[bb].terminator { self.visit_stack.push((bb, term.successors())); @@ -188,16 +194,14 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { } } -impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); +impl<'tcx> Iterator for Postorder<'_, 'tcx> { + type Item = BasicBlock; - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - let next = self.visit_stack.pop(); - if next.is_some() { - self.traverse_successor(); - } + fn next(&mut self) -> Option { + let (bb, _) = self.visit_stack.pop()?; + self.traverse_successor(); - next.map(|(bb, _)| (bb, &self.basic_blocks[bb])) + Some(bb) } fn size_hint(&self) -> (usize, Option) { @@ -215,10 +219,14 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { } } -/// Creates an iterator over the `Body`'s basic blocks, that: +/// Postorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that: /// - returns basic blocks in a postorder, /// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the /// postorder itself. +/// +/// See [`Postorder`]'s docs to learn what is postorder traversal. pub fn postorder<'a, 'tcx>( body: &'a Body<'tcx>, ) -> impl Iterator)> + ExactSizeIterator + DoubleEndedIterator @@ -226,7 +234,28 @@ pub fn postorder<'a, 'tcx>( reverse_postorder(body).rev() } -/// Reverse postorder traversal of a graph +/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular +/// order. +/// +/// This is clearer than writing `preorder` in cases where the order doesn't matter. +pub fn reachable<'a, 'tcx>( + body: &'a Body<'tcx>, +) -> impl 'a + Iterator)> { + preorder(body) +} + +/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. +pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet { + let mut iter = preorder(body); + iter.by_ref().for_each(drop); + iter.visited +} + +/// Reverse postorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that: +/// - returns basic blocks in a reverse postorder, +/// - makes use of the `BasicBlocks` CFG cache's reverse postorder. /// /// Reverse postorder is the reverse order of a postorder traversal. /// This is different to a preorder traversal and represents a natural @@ -246,65 +275,6 @@ pub fn postorder<'a, 'tcx>( /// A reverse postorder traversal of this graph is either `A B C D` or `A C B D` /// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to /// a topological sort. -/// -/// Construction of a `ReversePostorder` traversal requires doing a full -/// postorder traversal of the graph, therefore this traversal should be -/// constructed as few times as possible. Use the `reset` method to be able -/// to re-use the traversal -#[derive(Clone)] -pub struct ReversePostorder<'a, 'tcx> { - body: &'a Body<'tcx>, - blocks: Vec, - idx: usize, -} - -impl<'a, 'tcx> ReversePostorder<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> { - let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect(); - let len = blocks.len(); - ReversePostorder { body, blocks, idx: len } - } -} - -impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); - - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - if self.idx == 0 { - return None; - } - self.idx -= 1; - - self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb])) - } - - fn size_hint(&self) -> (usize, Option) { - (self.idx, Some(self.idx)) - } -} - -impl<'a, 'tcx> ExactSizeIterator for ReversePostorder<'a, 'tcx> {} - -/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular -/// order. -/// -/// This is clearer than writing `preorder` in cases where the order doesn't matter. -pub fn reachable<'a, 'tcx>( - body: &'a Body<'tcx>, -) -> impl 'a + Iterator)> { - preorder(body) -} - -/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. -pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet { - let mut iter = preorder(body); - (&mut iter).for_each(drop); - iter.visited -} - -/// Creates an iterator over the `Body`'s basic blocks, that: -/// - returns basic blocks in a reverse postorder, -/// - makes use of the `BasicBlocks` CFG cache's reverse postorder. pub fn reverse_postorder<'a, 'tcx>( body: &'a Body<'tcx>, ) -> impl Iterator)> + ExactSizeIterator + DoubleEndedIterator diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 61244b942893e..95c1848bc9bae 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -184,9 +184,11 @@ macro_rules! make_mir_visitor { visit_place_fns!($($mutability)?); + /// This is called for every constant in the MIR body and every `required_consts` + /// (i.e., including consts that have been dead-code-eliminated). fn visit_constant( &mut self, - constant: & $($mutability)? Constant<'tcx>, + constant: & $($mutability)? ConstOperand<'tcx>, location: Location, ) { self.super_constant(constant, location); @@ -815,7 +817,6 @@ macro_rules! make_mir_visitor { ty, user_ty, source_info, - internal: _, local_info: _, } = local_decl; @@ -870,20 +871,20 @@ macro_rules! make_mir_visitor { fn super_constant( &mut self, - constant: & $($mutability)? Constant<'tcx>, + constant: & $($mutability)? ConstOperand<'tcx>, location: Location ) { - let Constant { + let ConstOperand { span, user_ty: _, // no visit method for this - literal, + const_, } = constant; self.visit_span($(& $mutability)? *span); - match literal { - ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), - ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), - ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), + match const_ { + Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), + Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), + Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), } } @@ -1109,6 +1110,11 @@ macro_rules! visit_place_fns { self.visit_ty(&mut new_ty, TyContext::Location(location)); if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None } } + PlaceElem::Subtype(ty) => { + let mut new_ty = ty; + self.visit_ty(&mut new_ty, TyContext::Location(location)); + if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None } + } PlaceElem::Deref | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } @@ -1175,7 +1181,9 @@ macro_rules! visit_place_fns { location: Location, ) { match elem { - ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => { + ProjectionElem::OpaqueCast(ty) + | ProjectionElem::Subtype(ty) + | ProjectionElem::Field(_, ty) => { self.visit_ty(ty, TyContext::Location(location)); } ProjectionElem::Index(local) => { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 247fcd20c6ca5..8ba3764bcc317 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -116,9 +116,8 @@ impl EraseType for Result, mir::interpret::LitToConstError> { type Result = [u8; size_of::, mir::interpret::LitToConstError>>()]; } -impl EraseType for Result, mir::interpret::LitToConstError> { - type Result = - [u8; size_of::, mir::interpret::LitToConstError>>()]; +impl EraseType for Result, mir::interpret::LitToConstError> { + type Result = [u8; size_of::, mir::interpret::LitToConstError>>()]; } impl EraseType for Result, mir::interpret::ErrorHandled> { @@ -266,6 +265,7 @@ trivial! { rustc_middle::ty::adjustment::CoerceUnsizedInfo, rustc_middle::ty::AssocItem, rustc_middle::ty::AssocItemContainer, + rustc_middle::ty::Asyncness, rustc_middle::ty::BoundVariableKind, rustc_middle::ty::DeducedParamAttrs, rustc_middle::ty::Destructor, @@ -311,7 +311,7 @@ macro_rules! tcx_lifetime { tcx_lifetime! { rustc_middle::hir::Owner, rustc_middle::middle::exported_symbols::ExportedSymbol, - rustc_middle::mir::ConstantKind, + rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, rustc_middle::mir::ConstAlloc, rustc_middle::mir::ConstValue, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index af4c57e702f4b..113763450529c 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -12,7 +12,6 @@ use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::FieldIdx; /// Placeholder for `CrateNum`'s "local" counterpart #[derive(Copy, Clone, Debug)] @@ -360,30 +359,6 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { } } -impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) { - type CacheSelector = DefaultCacheSelector; - - fn default_span(&self, _: TyCtxt<'_>) -> Span { - DUMMY_SP - } -} - -impl<'tcx> Key for (mir::ConstValue<'tcx>, Ty<'tcx>) { - type CacheSelector = DefaultCacheSelector; - - fn default_span(&self, _: TyCtxt<'_>) -> Span { - DUMMY_SP - } -} - -impl<'tcx> Key for mir::ConstAlloc<'tcx> { - type CacheSelector = DefaultCacheSelector; - - fn default_span(&self, _: TyCtxt<'_>) -> Span { - DUMMY_SP - } -} - impl<'tcx> Key for ty::PolyTraitRef<'tcx> { type CacheSelector = DefaultCacheSelector; @@ -416,14 +391,6 @@ impl<'tcx> Key for GenericArg<'tcx> { } } -impl<'tcx> Key for mir::ConstantKind<'tcx> { - type CacheSelector = DefaultCacheSelector; - - fn default_span(&self, _: TyCtxt<'_>) -> Span { - DUMMY_SP - } -} - impl<'tcx> Key for ty::Const<'tcx> { type CacheSelector = DefaultCacheSelector; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b5529568ff2de..340c5a769dbc4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -7,7 +7,6 @@ #![allow(unused_parens)] use crate::dep_graph; -use crate::dep_graph::DepKind; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; @@ -45,7 +44,6 @@ use crate::traits::{ use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; use crate::ty::util::AlwaysRequiresDrop; -use crate::ty::GeneratorDiagnosticData; use crate::ty::TyCtxtFeed; use crate::ty::{ self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, @@ -231,7 +229,7 @@ rustc_queries! { action = { use rustc_hir::def::DefKind; match tcx.def_kind(key) { - DefKind::TyAlias { .. } => "expanding type alias", + DefKind::TyAlias => "expanding type alias", DefKind::TraitAlias => "expanding trait alias", _ => "computing type of", } @@ -253,6 +251,14 @@ rustc_queries! { } } + query type_alias_is_lazy(key: DefId) -> bool { + desc { |tcx| + "computing whether `{path}` is a lazy type alias", + path = tcx.def_path_str(key), + } + separate_provide_extern + } + query collect_return_position_impl_trait_in_trait_tys(key: DefId) -> Result<&'tcx FxHashMap>>, ErrorGuaranteed> { @@ -731,7 +737,7 @@ rustc_queries! { separate_provide_extern } - query asyncness(key: DefId) -> hir::IsAsync { + query asyncness(key: DefId) -> ty::Asyncness { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } separate_provide_extern } @@ -1101,16 +1107,6 @@ rustc_queries! { desc { "destructuring type level constant"} } - /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index - /// and its field values. This should only be used for pretty printing. - query try_destructure_mir_constant_for_diagnostics( - key: (mir::ConstValue<'tcx>, Ty<'tcx>) - ) -> Option> { - desc { "destructuring MIR constant"} - no_hash - eval_always - } - query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> mir::ConstValue<'tcx> { desc { "getting a &core::panic::Location referring to a span" } } @@ -2160,12 +2156,6 @@ rustc_queries! { desc { "computing the backend features for CLI flags" } } - query generator_diagnostic_data(key: DefId) -> &'tcx Option> { - arena_cache - desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result> { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a342b5231e9a5..34e5b02ba5be4 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -37,7 +37,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { pub eval_always: bool, pub dep_kind: DepKind, pub handle_cycle_error: HandleCycleError, - pub query_state: FieldOffset, QueryState>, + pub query_state: FieldOffset, QueryState>, pub query_cache: FieldOffset, C>, pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, @@ -53,7 +53,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, pub hash_result: HashResult, pub value_from_cycle_error: - fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> C::Value, + fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> C::Value, pub format_value: fn(&C::Value) -> String, } @@ -402,7 +402,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*, DepKind>, + pub $name: QueryState<$($K)*>, )* } @@ -516,7 +516,7 @@ macro_rules! define_feedable { } } None => { - let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); + let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::dep_kinds::$name, &key); let dep_node_index = tcx.dep_graph.with_feed_task( dep_node, tcx, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index ebc1c11902bcb..89934e4350e2e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -563,11 +563,11 @@ pub enum InlineAsmOperand<'tcx> { out_expr: Option, }, Const { - value: mir::ConstantKind<'tcx>, + value: mir::Const<'tcx>, span: Span, }, SymFn { - value: mir::ConstantKind<'tcx>, + value: mir::Const<'tcx>, span: Span, }, SymStatic { @@ -732,14 +732,18 @@ pub enum PatKind<'tcx> { }, /// One of the following: - /// * `&str`, which will be handled as a string pattern and thus exhaustiveness - /// checking will detect if you use the same string twice in different patterns. - /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly - /// its own value, similar to `&str`, but these values are much simpler. - /// * Opaque constants, that must not be matched structurally. So anything that does not derive - /// `PartialEq` and `Eq`. + /// * `&str` (represented as a valtree), which will be handled as a string pattern and thus + /// exhaustiveness checking will detect if you use the same string twice in different + /// patterns. + /// * integer, bool, char or float (represented as a valtree), which will be handled by + /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are + /// much simpler. + /// * Opaque constants (represented as `mir::ConstValue`), that must not be matched + /// structurally. So anything that does not derive `PartialEq` and `Eq`. + /// + /// These are always compared with the matched place using (the semantics of) `PartialEq`. Constant { - value: mir::ConstantKind<'tcx>, + value: mir::Const<'tcx>, }, Range(Box>), @@ -769,8 +773,8 @@ pub enum PatKind<'tcx> { #[derive(Clone, Debug, PartialEq, HashStable)] pub struct PatRange<'tcx> { - pub lo: mir::ConstantKind<'tcx>, - pub hi: mir::ConstantKind<'tcx>, + pub lo: mir::Const<'tcx>, + pub hi: mir::Const<'tcx>, pub end: RangeEnd, } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 681400dbb9481..b84e15688848b 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -26,13 +26,13 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized { walk_pat(self, pat); } - // Note: We don't have visitors for `ty::Const` and `mir::ConstantKind` + // Note: We don't have visitors for `ty::Const` and `mir::Const` // (even though these types occur in THIR) for consistency and to reduce confusion, // since the lazy creation of constants during thir construction causes most - // 'constants' to not be of type `ty::Const` or `mir::ConstantKind` at that + // 'constants' to not be of type `ty::Const` or `mir::Const` at that // stage (they are mostly still identified by `DefId` or `hir::Lit`, see // the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`). - // You have to manually visit `ty::Const` and `mir::ConstantKind` through the + // You have to manually visit `ty::Const` and `mir::Const` through the // other `visit*` functions. } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 1340e674568f4..99b750c9afc8c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -299,6 +299,10 @@ pub enum ObligationCauseCode<'tcx> { SizedYieldType, /// Inline asm operand type must be `Sized`. InlineAsmSized, + /// Captured closure type must be `Sized`. + SizedClosureCapture(LocalDefId), + /// Types live across generator yields must be `Sized`. + SizedGeneratorInterior(LocalDefId), /// `[expr; N]` requires `type_of(expr): Copy`. RepeatElementCopy { /// If element is a `const fn` we display a help message suggesting to move the @@ -378,6 +382,9 @@ pub enum ObligationCauseCode<'tcx> { /// `start` has wrong type StartFunctionType, + /// language function has wrong type + LangFunctionType(Symbol), + /// Intrinsic has wrong type IntrinsicType, diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index c3ed40867cf28..e7e40bee6b9de 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -1,30 +1,70 @@ +//! Data structure used to inspect trait solver behavior. +//! +//! During trait solving we optionally build "proof trees", the root of +//! which is a [GoalEvaluation] with [GoalEvaluationKind::Root]. These +//! trees are used to improve the debug experience and are also used by +//! the compiler itself to provide necessary context for error messages. +//! +//! Because each nested goal in the solver gets [canonicalized] separately +//! and we discard inference progress via "probes", we cannot mechanically +//! use proof trees without somehow "lifting up" data local to the current +//! `InferCtxt`. Any data used mechanically is therefore canonicalized and +//! stored as [CanonicalState]. As printing canonicalized data worsens the +//! debugging dumps, we do not simply canonicalize everything. +//! +//! This means proof trees contain inference variables and placeholders +//! local to a different `InferCtxt` which must not be used with the +//! current one. +//! +//! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html + use super::{ - CandidateSource, CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, QueryInput, - QueryResult, + CandidateSource, Canonical, CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, + QueryInput, QueryResult, }; -use crate::ty; +use crate::{infer::canonical::CanonicalVarValues, ty}; use format::ProofTreeFormatter; use std::fmt::{Debug, Write}; mod format; +/// Some `data` together with information about how they relate to the input +/// of the canonical query. +/// +/// This is only ever used as [CanonicalState]. Any type information in proof +/// trees used mechanically has to be canonicalized as we otherwise leak +/// inference variables from a nested `InferCtxt`. +#[derive(Debug, Clone, Copy, Eq, PartialEq, TypeFoldable, TypeVisitable)] +pub struct State<'tcx, T> { + pub var_values: CanonicalVarValues<'tcx>, + pub data: T, +} + +pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>; + #[derive(Debug, Eq, PartialEq)] pub enum CacheHit { Provisional, Global, } +/// When evaluating the root goals we also store the +/// original values for the `CanonicalVarValues` of the +/// canonicalized goal. We use this to map any [CanonicalState] +/// from the local `InferCtxt` of the solver query to +/// the `InferCtxt` of the caller. #[derive(Eq, PartialEq)] -pub enum GoalEvaluationKind { - Root, +pub enum GoalEvaluationKind<'tcx> { + Root { orig_values: Vec> }, Nested { is_normalizes_to_hack: IsNormalizesToHack }, } #[derive(Eq, PartialEq)] pub struct GoalEvaluation<'tcx> { pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, - pub kind: GoalEvaluationKind, + pub kind: GoalEvaluationKind<'tcx>, pub evaluation: CanonicalGoalEvaluation<'tcx>, + /// The nested goals from instantiating the query response. pub returned_goals: Vec>>, } @@ -66,6 +106,7 @@ pub struct GoalEvaluationStep<'tcx> { /// of a goal. #[derive(Eq, PartialEq)] pub struct Probe<'tcx> { + /// What happened inside of this probe in chronological order. pub steps: Vec>, pub kind: ProbeKind<'tcx>, } @@ -78,12 +119,21 @@ impl Debug for Probe<'_> { #[derive(Eq, PartialEq)] pub enum ProbeStep<'tcx> { - AddGoal(Goal<'tcx, ty::Predicate<'tcx>>), + /// We added a goal to the `EvalCtxt` which will get proven + /// the next time `EvalCtxt::try_evaluate_added_goals` is called. + AddGoal(CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>), + /// The inside of a `EvalCtxt::try_evaluate_added_goals` call. EvaluateGoals(AddedGoalsEvaluation<'tcx>), + /// A call to `probe` while proving the current goal. This is + /// used whenever there are multiple candidates to prove the + /// current goalby . NestedProbe(Probe<'tcx>), } -#[derive(Debug, PartialEq, Eq)] +/// What kind of probe we're in. In case the probe represents a candidate, or +/// the final result of the current goal - via [ProbeKind::Root] - we also +/// store the [QueryResult]. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum ProbeKind<'tcx> { /// The root inference context while proving a goal. Root { result: QueryResult<'tcx> }, diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index d33e83ae1edb3..5733be00adfae 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -41,7 +41,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result { let goal_text = match eval.kind { - GoalEvaluationKind::Root => "ROOT GOAL", + GoalEvaluationKind::Root { orig_values: _ } => "ROOT GOAL", GoalEvaluationKind::Nested { is_normalizes_to_hack } => match is_normalizes_to_hack { IsNormalizesToHack::No => "GOAL", IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index 09517200b0ddc..85181720d17ec 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -18,20 +18,20 @@ use crate::ty::{self, InferConst, Ty, TyCtxt}; /// Like subtyping, matching is really a binary relation, so the only /// important thing about the result is Ok/Err. Also, matching never /// affects any type variables or unification state. -pub struct Match<'tcx> { +pub struct MatchAgainstFreshVars<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, } -impl<'tcx> Match<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> { - Match { tcx, param_env } +impl<'tcx> MatchAgainstFreshVars<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> MatchAgainstFreshVars<'tcx> { + MatchAgainstFreshVars { tcx, param_env } } } -impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { +impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> { fn tag(&self) -> &'static str { - "Match" + "MatchAgainstFreshVars" } fn tcx(&self) -> TyCtxt<'tcx> { self.tcx diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 219927f5ab427..f50969dd967f8 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -448,7 +448,7 @@ impl<'tcx> AdtDef<'tcx> { Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid), Res::Def(DefKind::Struct, _) | Res::Def(DefKind::Union, _) - | Res::Def(DefKind::TyAlias { .. }, _) + | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::AssocTy, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 7c05deae90a58..e4069e11df274 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -348,9 +348,10 @@ impl<'tcx, D: TyDecoder>> Decodable for ty::Const<'tcx> { impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] { fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::>(), - ) + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) } } @@ -368,9 +369,10 @@ impl<'tcx, D: TyDecoder>> Decodable for AdtDef<'tcx> { impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::>(), - ) + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) } } @@ -566,6 +568,5 @@ impl_binder_encode_decode! { ty::TraitPredicate<'tcx>, ty::ExistentialPredicate<'tcx>, ty::TraitRef<'tcx>, - Vec>, ty::ExistentialTraitRef<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index ba871d6478bfe..2518f0cf2e9ce 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -339,24 +339,19 @@ impl<'tcx> Const<'tcx> { /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). - pub fn try_eval_bits( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ty: Ty<'tcx>, - ) -> Option { + pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { let int = self.try_eval_scalar_int(tcx, param_env)?; - assert_eq!(self.ty(), ty); - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = + tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env int.to_bits(size).ok() } #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env, ty) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9ff4b64f48b67..1ccb81dcb9b6b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -152,7 +152,7 @@ pub struct CtxtInterners<'tcx> { const_: InternedSet<'tcx, ConstData<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, - layout: InternedSet<'tcx, LayoutS>, + layout: InternedSet<'tcx, LayoutS>, adt_def: InternedSet<'tcx, AdtDefData>, external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>, predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>, @@ -318,7 +318,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })` + /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec>>, } @@ -395,7 +395,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|v| { mk(ty::ReLateBound( ty::DebruijnIndex::from(i), - ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) }, + ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon }, )) }) .collect() @@ -554,6 +554,10 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, + /// Hooks to be able to register functions in other crates that can then still + /// be called from rustc_middle. + pub(crate) hooks: crate::hooks::Providers, + untracked: Untracked, pub query_system: QuerySystem<'tcx>, @@ -703,6 +707,7 @@ impl<'tcx> TyCtxt<'tcx> { dep_graph: DepGraph, query_kinds: &'tcx [DepKindStruct<'tcx>], query_system: QuerySystem<'tcx>, + hooks: crate::hooks::Providers, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); @@ -721,6 +726,7 @@ impl<'tcx> TyCtxt<'tcx> { hir_arena, interners, dep_graph, + hooks, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, @@ -1051,16 +1057,21 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region. - pub fn is_suitable_region(self, region: Region<'tcx>) -> Option { - let (suitable_region_binding_scope, bound_region) = match *region { - ty::ReFree(ref free_region) => { - (free_region.scope.expect_local(), free_region.bound_region) + pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option { + let (suitable_region_binding_scope, bound_region) = loop { + let def_id = match region.kind() { + ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?, + ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(), + _ => return None, // not a free region + }; + let scope = self.local_parent(def_id); + if self.def_kind(scope) == DefKind::OpaqueTy { + // Lifetime params of opaque types are synthetic and thus irrelevant to + // diagnostics. Map them back to their origin! + region = self.map_rpit_lifetime_to_fn_lifetime(def_id); + continue; } - ty::ReEarlyBound(ref ebr) => ( - self.local_parent(ebr.def_id.expect_local()), - ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name), - ), - _ => return None, // not a free region + break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); }; let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) { @@ -1068,7 +1079,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(Node::ImplItem(..)) => { self.is_bound_region_in_impl_item(suitable_region_binding_scope) } - _ => return None, + _ => false, }; Some(FreeRegionInfo { @@ -1108,7 +1119,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) && let hir::TyKind::Path(hir::QPath::Resolved( None, - hir::Path { res: hir::def::Res::Def(DefKind::TyAlias { .. }, def_id), .. }, )) = hir_output.kind + hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind && let Some(local_id) = def_id.as_local() && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics() @@ -1378,7 +1389,6 @@ impl<'tcx> TyCtxt<'tcx> { Placeholder, Generator, GeneratorWitness, - GeneratorWitnessMIR, Dynamic, Closure, Tuple, @@ -1516,7 +1526,7 @@ direct_interners! { region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>, const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, - layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>, + layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>): ExternalConstraints -> ExternalConstraints<'tcx>, diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index e7ebb985ca411..f03813a459b6a 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -493,7 +493,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let DefKind::TyAlias { .. } | DefKind::AssocTy = self.tcx.def_kind(parent) + if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { @@ -577,7 +577,7 @@ impl<'tcx> FallibleTypeFolder> for MakeSuggestableFolder<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let hir::def::DefKind::TyAlias { .. } | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) + if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index f939d466078a5..459c8dfb59602 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -242,8 +242,7 @@ impl<'tcx> Ty<'tcx> { ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), - ty::GeneratorWitness(..) | - ty::GeneratorWitnessMIR(..) => "generator witness".into(), + ty::GeneratorWitness(..) => "generator witness".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), ty::Infer(ty::IntVar(_)) => "integer".into(), ty::Infer(ty::FloatVar(_)) => "floating-point number".into(), @@ -295,7 +294,7 @@ impl<'tcx> Ty<'tcx> { ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => "generator witness".into(), + ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 668aa4521c101..16935d5b38042 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -29,8 +29,7 @@ pub enum SimplifiedType { Trait(DefId), Closure(DefId), Generator(DefId), - GeneratorWitness(usize), - GeneratorWitnessMIR(DefId), + GeneratorWitness(DefId), Function(usize), Placeholder, } @@ -130,10 +129,7 @@ pub fn simplify_type<'tcx>( ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)), - ty::GeneratorWitness(tys) => { - Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len())) - } - ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)), + ty::GeneratorWitness(def_id, _) => Some(SimplifiedType::GeneratorWitness(def_id)), ty::Never => Some(SimplifiedType::Never), ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), @@ -169,7 +165,7 @@ impl SimplifiedType { | SimplifiedType::Trait(d) | SimplifiedType::Closure(d) | SimplifiedType::Generator(d) - | SimplifiedType::GeneratorWitnessMIR(d) => Some(d), + | SimplifiedType::GeneratorWitness(d) => Some(d), _ => None, } } @@ -240,7 +236,6 @@ impl DeepRejectCtxt { | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"), @@ -342,7 +337,7 @@ impl DeepRejectCtxt { ty::Error(_) => true, - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { + ty::GeneratorWitness(..) => { bug!("unexpected obligation type: {:?}", obligation_ty) } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 231635c086e3b..7ed31fbbfd885 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -127,11 +127,7 @@ impl FlagComputation { self.add_ty(args.tupled_upvars_ty()); } - &ty::GeneratorWitness(ts) => { - self.bound_computation(ts, |flags, ts| flags.add_tys(ts)); - } - - ty::GeneratorWitnessMIR(_, args) => { + ty::GeneratorWitness(_, args) => { let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); self.add_args(args); diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 77cf6bee79d64..00529a1e066cc 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -385,7 +385,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None))) + .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) .expect_region(); let br = ty::BoundRegion { var, kind }; ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 2b75f6c4e8f23..0a425be52ffb5 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -118,7 +118,7 @@ impl<'tcx> Instance<'tcx> { /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -580,7 +580,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn subst_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T where T: TypeFoldable> + Copy, { @@ -593,7 +593,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] - pub fn subst_mir_and_normalize_erasing_regions( + pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -603,26 +603,31 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.subst_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.normalize_erasing_regions(param_env, v.skip_binder()) } } #[inline(always)] - pub fn try_subst_mir_and_normalize_erasing_regions( + pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, v: EarlyBinder, ) -> Result> where - T: TypeFoldable> + Clone, + T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { - tcx.try_subst_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) } else { - tcx.try_normalize_erasing_regions(param_env, v.skip_binder()) + // We're using `instantiate_identity` as e.g. + // `FnPtrShim` is separately generated for every + // instantiation of the `FnDef`, so the MIR body + // is already instantiated. Any generic parameters it + // contains are generic parameters from the caller. + tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity()) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8b425ce0267d2..bccf5e8398749 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -810,7 +810,6 @@ where | ty::Never | ty::FnDef(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Foreign(..) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dbff13fdd8e9f..b7d2e3d9493f9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -106,9 +106,8 @@ pub use self::sty::{ }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ - CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, - UserTypeAnnotationIndex, + CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, TypeckResults, + UserType, UserTypeAnnotationIndex, }; pub mod _match; @@ -280,6 +279,19 @@ impl fmt::Display for ImplPolarity { } } +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum Asyncness { + Yes, + No, +} + +impl Asyncness { + pub fn is_async(self) -> bool { + matches!(self, Asyncness::Yes) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] pub enum Visibility { /// Visible everywhere (including in other crates). @@ -566,11 +578,6 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> { pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo>>>); impl<'tcx> Clause<'tcx> { - pub fn from_projection_clause(tcx: TyCtxt<'tcx>, pred: PolyProjectionPredicate<'tcx>) -> Self { - let pred: Predicate<'tcx> = pred.to_predicate(tcx); - pred.expect_clause() - } - pub fn as_predicate(self) -> Predicate<'tcx> { Predicate(self.0) } @@ -1284,12 +1291,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef } } +impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) } } +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { let p: Predicate<'tcx> = self.to_predicate(tcx); @@ -1328,9 +1348,10 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { } } -impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() } } @@ -1731,30 +1752,9 @@ impl<'tcx> ParamEnv<'tcx> { Self::new(List::empty(), self.reveal()) } - /// Creates a suitable environment in which to perform trait - /// queries on the given value. When type-checking, this is simply - /// the pair of the environment plus value. But when reveal is set to - /// All, then if `value` does not reference any type parameters, we will - /// pair it with the empty environment. This improves caching and is generally - /// invisible. - /// - /// N.B., we preserve the environment when type-checking because it - /// is possible for the user to have wacky where-clauses like - /// `where Box: Copy`, which are clearly never - /// satisfiable. We generally want to behave as if they were true, - /// although the surrounding function is never reachable. + /// Creates a pair of param-env and value for use in queries. pub fn and>>(self, value: T) -> ParamEnvAnd<'tcx, T> { - match self.reveal() { - Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, - - Reveal::All => { - if value.is_global() { - ParamEnvAnd { param_env: self.without_caller_bounds(), value } - } else { - ParamEnvAnd { param_env: self, value } - } - } - } + ParamEnvAnd { param_env: self, value } } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 2415d50b2784a..fd125af2074e4 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -134,8 +134,9 @@ impl<'tcx> TyCtxt<'tcx> { /// in-scope substitutions and then normalizing any associated /// types. /// Panics if normalization fails. In case normalization might fail - /// use `try_subst_and_normalize_erasing_regions` instead. - pub fn subst_and_normalize_erasing_regions( + /// use `try_instantiate_and_normalize_erasing_regions` instead. + #[instrument(level = "debug", skip(self))] + pub fn instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -144,22 +145,16 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.normalize_erasing_regions(param_env, substituted) } /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then trying to normalize any associated - /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// types. Contrary to `instantiate_and_normalize_erasing_regions` this does /// not assume that normalization succeeds. - pub fn try_subst_and_normalize_erasing_regions( + #[instrument(level = "debug", skip(self))] + pub fn try_instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -168,13 +163,6 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.try_normalize_erasing_regions(param_env, substituted) } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 0ff5ac9030426..6491936c21921 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -157,9 +157,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { Ty::new_generator(self.tcx, def_id, args, movability) } - ty::GeneratorWitnessMIR(def_id, args) => { + ty::GeneratorWitness(def_id, args) => { let args = self.fold_closure_args(def_id, args); - Ty::new_generator_witness_mir(self.tcx, def_id, args) + Ty::new_generator_witness(self.tcx, def_id, args) } ty::Param(param) => { diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index f1c38984296c7..9aa673e4418c6 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -62,6 +62,7 @@ trivially_parameterized_over_tcx! { crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, + ty::Asyncness, ty::DeducedParamAttrs, ty::Generics, ty::ImplPolarity, @@ -131,5 +132,4 @@ parameterized_over_tcx! { ty::Predicate, ty::Clause, ty::ClauseKind, - ty::GeneratorDiagnosticData, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 05871d0bc39d1..aa8e2e30715eb 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -271,7 +271,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::Generator(def_id, _, _) - | ty::GeneratorWitnessMIR(def_id, _) + | ty::GeneratorWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), ty::Bool @@ -286,7 +286,6 @@ fn characteristic_def_id_of_type_cached<'a>( | ty::Infer(_) | ty::Bound(..) | ty::Error(_) - | ty::GeneratorWitness(..) | ty::Never | ty::Float(_) => None, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 0ee63e92848f7..2d7350387ca78 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -360,7 +360,7 @@ pub trait PrettyPrinter<'tcx>: self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait - | DefKind::TyAlias { .. } | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind + | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind { } else { // If not covered above, like for example items out of `impl` blocks, fallback. @@ -766,7 +766,7 @@ pub trait PrettyPrinter<'tcx>: let parent = self.tcx().parent(def_id); match self.tcx().def_kind(parent) { - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { // NOTE: I know we should check for NO_QUERIES here, but it's alright. // `type_of` on a type alias or assoc type should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = @@ -795,7 +795,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!("str"), ty::Generator(did, args, movability) => { - p!(write("[")); + p!(write("{{")); let generator_kind = self.tcx().generator_kind(did).unwrap(); let should_print_movability = self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen; @@ -836,13 +836,10 @@ pub trait PrettyPrinter<'tcx>: } } - p!("]") + p!("}}") } - ty::GeneratorWitness(types) => { - p!(in_binder(&types)); - } - ty::GeneratorWitnessMIR(did, args) => { - p!(write("[")); + ty::GeneratorWitness(did, args) => { + p!(write("{{")); if !self.tcx().sess.verbose() { p!("generator witness"); // FIXME(eddyb) should use `def_span`. @@ -861,10 +858,10 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(did, args)); } - p!("]") + p!("}}") } ty::Closure(did, args) => { - p!(write("[")); + p!(write("{{")); if !self.should_print_verbose() { p!(write("closure")); // FIXME(eddyb) should use `def_span`. @@ -904,7 +901,7 @@ pub trait PrettyPrinter<'tcx>: p!(")"); } } - p!("]"); + p!("}}"); } ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"), ty::Slice(ty) => p!("[", print(ty), "]"), @@ -1061,7 +1058,7 @@ pub trait PrettyPrinter<'tcx>: } for (assoc_item_def_id, term) in assoc_items { - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, + // Skip printing `<{generator@} as Generator<_>>::Return` from async blocks, // unless we can find out what generator return type it comes from. let term = if let Some(ty) = term.skip_binder().ty() && let ty::Alias(ty::Projection, proj) = ty.kind() @@ -2333,7 +2330,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon(..) | ty::BrEnv => r, + ty::BrAnon | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; @@ -2454,7 +2451,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon(..) | ty::BrEnv => { + ty::BrAnon | ty::BrEnv => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { @@ -3001,7 +2998,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N match child.res { def::Res::Def(DefKind::AssocTy, _) => {} - def::Res::Def(DefKind::TyAlias { .. }, _) => {} + def::Res::Def(DefKind::TyAlias, _) => {} def::Res::Def(defkind, def_id) => { if let Some(ns) = defkind.ns() { collect_fn(&child.ident, ns, def_id); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 47512d350e546..e9d763afa68a0 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -453,24 +453,14 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_generator(tcx, a_id, args, movability)) } - (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { - // Wrap our types with a temporary GeneratorWitness struct - // inside the binder so we can related them - let a_types = a_types.map_bound(GeneratorWitness); - 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(Ty::new_generator_witness(tcx, types)) - } - - (&ty::GeneratorWitnessMIR(a_id, a_args), &ty::GeneratorWitnessMIR(b_id, b_args)) + (&ty::GeneratorWitness(a_id, a_args), &ty::GeneratorWitness(b_id, b_args)) if a_id == b_id => { // All GeneratorWitness types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. let args = relation.relate(a_args, b_args)?; - Ok(Ty::new_generator_witness_mir(tcx, a_id, args)) + Ok(Ty::new_generator_witness(tcx, a_id, args)) } (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 268339ed4028c..2adbe9e030997 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(span) => write!(f, "BrAnon({span:?})"), + ty::BrAnon => write!(f, "BrAnon"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({name})") @@ -479,7 +479,6 @@ TrivialTypeTraversalImpls! { ::rustc_target::asm::InlineAsmRegOrRegClass, crate::mir::coverage::CounterId, crate::mir::coverage::ExpressionId, - crate::mir::coverage::MappedExpressionIndex, crate::mir::Local, crate::mir::Promoted, crate::traits::Reveal, @@ -658,9 +657,8 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::Generator(did, args, movability) => { ty::Generator(did, args.try_fold_with(folder)?, movability) } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), - ty::GeneratorWitnessMIR(did, args) => { - ty::GeneratorWitnessMIR(did, args.try_fold_with(folder)?) + ty::GeneratorWitness(did, args) => { + ty::GeneratorWitness(did, args.try_fold_with(folder)?) } ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), @@ -709,8 +707,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty.visit_with(visitor) } ty::Generator(_did, ref args, _) => args.visit_with(visitor), - ty::GeneratorWitness(ref types) => types.visit_with(visitor), - ty::GeneratorWitnessMIR(_did, ref args) => args.visit_with(visitor), + ty::GeneratorWitness(_did, ref args) => args.visit_with(visitor), ty::Closure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e3e014a3b2a81..e5f418bbb4b11 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -69,7 +69,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(Option), + BrAnon, /// Named region parameters for functions (a in &'a T) /// @@ -725,7 +725,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) } ExistentialPredicate::Projection(p) => { - ty::Clause::from_projection_clause(tcx, self.rebind(p.with_self_ty(tcx, self_ty))) + self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) } ExistentialPredicate::AutoTrait(did) => { let generics = tcx.generics_of(did); @@ -1223,7 +1223,7 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy => ty::Projection, DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias { .. } => ty::Weak, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } @@ -1465,7 +1465,7 @@ impl<'tcx> Region<'tcx> { bound_region: ty::BoundRegion, ) -> Region<'tcx> { // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region + if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) && let Some(re) = inner.get(var.as_usize()).copied() { @@ -1959,7 +1959,7 @@ impl<'tcx> Ty<'tcx> { (kind, tcx.def_kind(alias_ty.def_id)), (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Weak, DefKind::TyAlias { .. }) + | (ty::Weak, DefKind::TyAlias) ); Ty::new(tcx, Alias(kind, alias_ty)) } @@ -2164,19 +2164,11 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_generator_witness( - tcx: TyCtxt<'tcx>, - types: ty::Binder<'tcx, &'tcx List>>, - ) -> Ty<'tcx> { - Ty::new(tcx, GeneratorWitness(types)) - } - - #[inline] - pub fn new_generator_witness_mir( tcx: TyCtxt<'tcx>, id: DefId, args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - Ty::new(tcx, GeneratorWitnessMIR(id, args)) + Ty::new(tcx, GeneratorWitness(id, args)) } // misc @@ -2550,7 +2542,7 @@ impl<'tcx> Ty<'tcx> { /// Checks whether a type recursively contains any closure /// - /// Example: `Option<[closure@file.rs:4:20]>` returns true + /// Example: `Option<{closure@file.rs:4:20}>` returns true pub fn contains_closure(self) -> bool { struct ContainsClosureVisitor; @@ -2706,7 +2698,6 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Closure(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Tuple(_) | ty::Error(_) @@ -2742,7 +2733,6 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -2831,7 +2821,6 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -2894,7 +2883,7 @@ impl<'tcx> Ty<'tcx> { // anything with custom metadata it might be more complicated. ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false, - ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => false, + ty::Generator(..) | ty::GeneratorWitness(..) => false, // Might be, but not "trivial" so just giving the safe answer. ty::Adt(..) | ty::Closure(..) => false, @@ -2946,6 +2935,11 @@ impl<'tcx> Ty<'tcx> { } } + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or substituted. This includes all primitive types, but also + /// things like ADTs and trait objects, sice even if their arguments or + /// nested types may be further simplified, the outermost [`TyKind`] or + /// type constructor remains the same. pub fn is_known_rigid(self) -> bool { match self.kind() { Bool @@ -2965,8 +2959,7 @@ impl<'tcx> Ty<'tcx> { | Dynamic(_, _, _) | Closure(_, _) | Generator(_, _, _) - | GeneratorWitness(_) - | GeneratorWitnessMIR(_, _) + | GeneratorWitness(..) | Never | Tuple(_) => true, Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, @@ -3017,7 +3010,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(RegionKind<'_>, 28); + static_assert_size!(RegionKind<'_>, 24); static_assert_size!(TyKind<'_>, 32); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 69c4c588c44a5..a44224e4dc7e2 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -189,10 +189,6 @@ pub struct TypeckResults<'tcx> { /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`. pub rvalue_scopes: RvalueScopes, - /// Stores the type, expression, span and optional scope span of all types - /// that are live across the yield of this generator (if a generator). - pub generator_interior_types: ty::Binder<'tcx, Vec>>, - /// Stores the predicates that apply on generator witness types. /// formatting modified file tests/ui/generator/retain-resume-ref.rs pub generator_interior_predicates: @@ -212,49 +208,6 @@ pub struct TypeckResults<'tcx> { offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec)>, } -/// Whenever a value may be live across a generator yield, the type of that value winds up in the -/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such -/// captured types that can be useful for diagnostics. In particular, it stores the span that -/// caused a given type to be recorded, along with the scope that enclosed the value (which can -/// be used to find the await that the value is live across). -/// -/// For example: -/// -/// ```ignore (pseudo-Rust) -/// async move { -/// let x: T = expr; -/// foo.await -/// ... -/// } -/// ``` -/// -/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for -/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`. -#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct GeneratorInteriorTypeCause<'tcx> { - /// Type of the captured binding. - pub ty: Ty<'tcx>, - /// Span of the binding that was captured. - pub span: Span, - /// Span of the scope of the captured binding. - pub scope_span: Option, - /// Span of `.await` or `yield` expression. - pub yield_span: Span, - /// Expr which the type evaluated from. - pub expr: Option, -} - -// This type holds diagnostic information on generators and async functions across crate boundaries -// and is used to provide better error messages -#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)] -pub struct GeneratorDiagnosticData<'tcx> { - pub generator_interior_types: ty::Binder<'tcx, Vec>>, - pub hir_owner: DefId, - pub nodes_types: ItemLocalMap>, - pub adjustments: ItemLocalMap>>, -} - impl<'tcx> TypeckResults<'tcx> { pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> { TypeckResults { @@ -278,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> { closure_min_captures: Default::default(), closure_fake_reads: Default::default(), rvalue_scopes: Default::default(), - generator_interior_types: ty::Binder::dummy(Default::default()), generator_interior_predicates: Default::default(), treat_byte_string_as_slice: Default::default(), closure_size_eval: Default::default(), @@ -351,28 +303,6 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types } } - pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> { - let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| { - vec.iter() - .map(|item| { - GeneratorInteriorTypeCause { - ty: item.ty, - span: item.span, - scope_span: item.scope_span, - yield_span: item.yield_span, - expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment - } - }) - .collect::>() - }); - GeneratorDiagnosticData { - generator_interior_types: generator_interior_type, - hir_owner: self.hir_owner.to_def_id(), - nodes_types: self.node_types.clone(), - adjustments: self.adjustments.clone(), - } - } - pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> { self.node_type_opt(id).unwrap_or_else(|| { bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id))) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 564f982f842ed..31b52677b2797 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -156,7 +156,7 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Enum | DefKind::Trait | DefKind::OpaqueTy - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -855,7 +855,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { let hidden_ty = bty.instantiate(self.tcx, args); self.fold_ty(hidden_ty); } - let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, args); + let expanded_ty = Ty::new_generator_witness(self.tcx, def_id, args); self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty } @@ -888,7 +888,7 @@ impl<'tcx> TypeFolder> for OpaqueTypeExpander<'tcx> { t }; if self.expand_generators { - if let ty::GeneratorWitnessMIR(def_id, args) = *t.kind() { + if let ty::GeneratorWitness(def_id, args) = *t.kind() { t = self.expand_generator(def_id, args).unwrap_or(t); } } @@ -1025,8 +1025,7 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Foreign(_) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1065,8 +1064,7 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Foreign(_) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1194,10 +1192,7 @@ impl<'tcx> Ty<'tcx> { false } - ty::Foreign(_) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Error(_) => false, + ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } } @@ -1293,7 +1288,6 @@ pub fn needs_drop_components<'tcx>( | ty::FnPtr(_) | ty::Char | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::RawPtr(_) | ty::Ref(..) | ty::Str => Ok(SmallVec::new()), @@ -1364,11 +1358,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // Not trivial because they have components, and instead of looking inside, // we'll just perform trait selection. - ty::Closure(..) - | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) - | ty::Adt(..) => false, + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Adt(..) => false, ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 7c3d9ed390a22..a86ff64bd0ca3 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -190,14 +190,11 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Adt(_, args) | ty::Closure(_, args) | ty::Generator(_, args, _) - | ty::GeneratorWitnessMIR(_, args) + | ty::GeneratorWitness(_, args) | ty::FnDef(_, args) => { stack.extend(args.iter().rev()); } ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)), - ty::GeneratorWitness(ts) => { - stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into())); - } ty::FnPtr(sig) => { stack.push(sig.skip_binder().output().into()); stack.extend(sig.skip_binder().inputs().iter().copied().rev().map(|ty| ty.into())); diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 1b845334c49b5..9f1e4ac11c234 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>( &body[block].terminator { debug!("find_self_call: func={:?}", func); - if let Operand::Constant(box Constant { literal, .. }) = func { - if let ty::FnDef(def_id, fn_args) = *literal.ty().kind() { + if let Operand::Constant(box ConstOperand { const_, .. }) = func { + if let ty::FnDef(def_id, fn_args) = *const_.ty().kind() { if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) = tcx.opt_associated_item(def_id) { diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index 53b4257899bce..8c95988477d9c 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -5,3 +5,27 @@ pub mod find_self_call; pub use call_kind::{call_kind, CallDesugaringKind, CallKind}; pub use find_self_call::find_self_call; + +#[derive(Default, Copy, Clone)] +pub struct Providers { + pub queries: rustc_middle::query::Providers, + pub extern_queries: rustc_middle::query::ExternProviders, + pub hooks: rustc_middle::hooks::Providers, +} + +/// Backwards compatibility hack to keep the diff small. This +/// gives direct access to the `queries` field's fields, which +/// are what almost everything wants access to. +impl std::ops::DerefMut for Providers { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.queries + } +} + +impl std::ops::Deref for Providers { + type Target = rustc_middle::query::Providers; + + fn deref(&self) -> &Self::Target { + &self.queries + } +} diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 962faf56cb87d..578d8e7a975ea 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::DepKind; +use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; @@ -13,34 +13,22 @@ use rustc_span::{ErrorGuaranteed, Span}; use std::fmt::Write; -impl<'tcx> Value, DepKind> for Ty<'_> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Ty<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> 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<'_>>(Ty::new_error(tcx, guar)) } } } -impl<'tcx> Value, DepKind> for Result>, CyclePlaceholder> { - fn from_cycle_error( - _tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Result>, CyclePlaceholder> { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } } -impl<'tcx> Value, DepKind> for ty::SymbolName<'_> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::SymbolName<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { @@ -51,16 +39,12 @@ impl<'tcx> Value, DepKind> for ty::SymbolName<'_> { } } -impl<'tcx> Value, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - stack: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo], guar: ErrorGuaranteed) -> Self { let err = Ty::new_error(tcx, guar); let arity = if let Some(frame) = stack.get(0) - && frame.query.dep_kind == DepKind::fn_sig + && frame.query.dep_kind == dep_kinds::fn_sig && let Some(def_id) = frame.query.def_id && let Some(node) = tcx.hir().get_if_local(def_id) && let Some(sig) = node.fn_sig() @@ -85,16 +69,12 @@ impl<'tcx> Value, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { } } -impl<'tcx> Value, DepKind> for Representability { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Representability { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in cycle { - if info.query.dep_kind == DepKind::representability + if info.query.dep_kind == dep_kinds::representability && let Some(field_id) = info.query.def_id && let Some(field_id) = field_id.as_local() && let Some(DefKind::Field) = info.query.def_kind @@ -108,7 +88,7 @@ impl<'tcx> Value, DepKind> for Representability { } } for info in cycle { - if info.query.dep_kind == DepKind::representability_adt_ty + if info.query.dep_kind == dep_kinds::representability_adt_ty && let Some(def_id) = info.query.ty_adt_id && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) @@ -121,32 +101,20 @@ impl<'tcx> Value, DepKind> for Representability { } } -impl<'tcx> Value, DepKind> for ty::EarlyBinder> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::EarlyBinder> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle, guar)) } } -impl<'tcx> Value, DepKind> for ty::EarlyBinder>> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::EarlyBinder>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle, guar)) } } -impl<'tcx, T> Value, DepKind> for Result> { - fn from_cycle_error( - _tcx: TyCtxt<'tcx>, - _cycle: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx, T> Value> for Result> { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, // tcx.arena.alloc is pretty much equal to leaking). @@ -249,7 +217,7 @@ fn find_item_ty_spans( match ty.kind { hir::TyKind::Path(hir::QPath::Resolved(_, path)) => { if let Res::Def(kind, def_id) = path.res - && !matches!(kind, DefKind::TyAlias { .. }) { + && !matches!(kind, DefKind::TyAlias) { let check_params = def_id.as_local().map_or(true, |def_id| { if def_id == needle { spans.push(ty.span); diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 938f3edd31b05..ce021923f647f 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -229,6 +229,9 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern +mir_build_non_partial_eq_match = + to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` + mir_build_nontrivial_structural_match = to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]` diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index 4f1623b4c6a7c..fddcf9de7c7c9 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -49,7 +49,7 @@ impl<'tcx> CFG<'tcx> { block: BasicBlock, source_info: SourceInfo, temp: Place<'tcx>, - constant: Constant<'tcx>, + constant: ConstOperand<'tcx>, ) { self.push_assign( block, @@ -70,10 +70,10 @@ impl<'tcx> CFG<'tcx> { block, source_info, place, - Rvalue::Use(Operand::Constant(Box::new(Constant { + Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: source_info.span, user_ty: None, - literal: ConstantKind::zero_sized(tcx.types.unit), + const_: Const::zero_sized(tcx.types.unit), }))), ); } diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 0eff2df136622..fd2c57a0a6f12 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -100,7 +100,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { expected: "constant pattern".to_string(), }); }; - values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty)); + values.push(value.eval_bits(self.tcx, self.param_env)); targets.push(self.parse_block(arm.body)?); } @@ -283,12 +283,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::StaticRef { alloc_id, ty, .. } => { let const_val = ConstValue::Scalar(Scalar::from_pointer((*alloc_id).into(), &self.tcx)); - let literal = ConstantKind::Val(const_val, *ty); + let const_ = Const::Val(const_val, *ty); - Ok(Operand::Constant(Box::new(Constant { + Ok(Operand::Constant(Box::new(ConstOperand { span: expr.span, user_ty: None, - literal + const_ }))) }, ) @@ -301,7 +301,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { | ExprKind::NonHirLiteral { .. } | ExprKind::ConstBlock { .. } => Ok({ let value = as_constant_inner(expr, |_| None, self.tcx); - value.literal.eval_bits(self.tcx, self.param_env, value.ty()) + value.const_.eval_bits(self.tcx, self.param_env) }), ) } 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 d8232199e0143..4ed49e787383d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -15,7 +15,7 @@ use rustc_target::abi::Size; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! - pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { + pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> { let this = self; let tcx = this.tcx; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; @@ -42,62 +42,62 @@ pub fn as_constant_inner<'tcx>( expr: &Expr<'tcx>, push_cuta: impl FnMut(&Box>) -> Option, tcx: TyCtxt<'tcx>, -) -> Constant<'tcx> { +) -> ConstOperand<'tcx> { let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; match *kind { ExprKind::Literal { lit, neg } => { - let literal = - match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { - Ok(c) => c, - Err(LitToConstError::Reported(guar)) => { - ConstantKind::Ty(ty::Const::new_error(tcx, guar, ty)) - } - Err(LitToConstError::TypeError) => { - bug!("encountered type error in `lit_to_mir_constant`") - } - }; - - Constant { span, user_ty: None, literal } + let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) + { + Ok(c) => c, + Err(LitToConstError::Reported(guar)) => { + Const::Ty(ty::Const::new_error(tcx, guar, ty)) + } + Err(LitToConstError::TypeError) => { + bug!("encountered type error in `lit_to_mir_constant`") + } + }; + + ConstOperand { span, user_ty: None, const_ } } ExprKind::NonHirLiteral { lit, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); + let const_ = Const::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); - Constant { span, user_ty, literal } + ConstOperand { span, user_ty, const_ } } ExprKind::ZstLiteral { ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - let literal = ConstantKind::Val(ConstValue::ZeroSized, ty); + let const_ = Const::Val(ConstValue::ZeroSized, ty); - Constant { span, user_ty, literal } + ConstOperand { span, user_ty, const_ } } ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); let uneval = mir::UnevaluatedConst::new(def_id, args); - let literal = ConstantKind::Unevaluated(uneval, ty); + let const_ = Const::Unevaluated(uneval, ty); - Constant { user_ty, span, literal } + ConstOperand { user_ty, span, const_ } } ExprKind::ConstParam { param, def_id: _ } => { let const_param = ty::Const::new_param(tcx, param, expr.ty); - let literal = ConstantKind::Ty(const_param); + let const_ = Const::Ty(const_param); - Constant { user_ty: None, span, literal } + ConstOperand { user_ty: None, span, const_ } } ExprKind::ConstBlock { did: def_id, args } => { let uneval = mir::UnevaluatedConst::new(def_id, args); - let literal = ConstantKind::Unevaluated(uneval, ty); + let const_ = Const::Unevaluated(uneval, ty); - Constant { user_ty: None, span, literal } + ConstOperand { user_ty: None, span, const_ } } ExprKind::StaticRef { alloc_id, ty, .. } => { let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); - let literal = ConstantKind::Val(const_val, ty); + let const_ = Const::Val(const_val, ty); - Constant { span, user_ty: None, literal } + ConstOperand { span, user_ty: None, const_ } } _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } @@ -107,7 +107,7 @@ pub fn as_constant_inner<'tcx>( fn lit_to_mir_constant<'tcx>( tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>, -) -> Result, LitToConstError> { +) -> Result, LitToConstError> { let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { let param_ty = ty::ParamEnv::reveal_all().and(ty); @@ -173,5 +173,5 @@ fn lit_to_mir_constant<'tcx>( _ => return Err(LitToConstError::TypeError), }; - Ok(ConstantKind::Val(value, ty)) + Ok(Const::Val(value, ty)) } 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 2e7ef265a93c2..4aff406b37686 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -102,7 +102,7 @@ fn convert_to_hir_projections_and_truncate_for_capture( continue; } // These do not affect anything, they just make sure we know the right type. - ProjectionElem::OpaqueCast(_) => continue, + ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(..) => continue, ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { @@ -709,6 +709,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ProjectionElem::Field(..) | ProjectionElem::Downcast(..) | ProjectionElem::OpaqueCast(..) + | ProjectionElem::Subtype(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => (), } 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 3220a184d49ba..afb65ffbe8c95 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -183,7 +183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator auto-trait // determination. See the comment about `box` at `yield_in_scope`. - let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal()); + let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span)); this.cfg.push( block, Statement { source_info, kind: StatementKind::StorageLive(result) }, @@ -249,7 +249,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> { let range_val = - ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty)); + Const::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty)); let lit_op = this.literal_operand(expr.span, range_val); let is_bin_op = this.temp(bool_ty, expr_span); this.cfg.push_assign( @@ -485,10 +485,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { block = unpack!(this.stmt_expr(block, expr, None)); - block.and(Rvalue::Use(Operand::Constant(Box::new(Constant { + block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: expr_span, user_ty: None, - literal: ConstantKind::zero_sized(this.tcx.types.unit), + const_: Const::zero_sized(this.tcx.types.unit), })))) } @@ -817,7 +817,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); let size = self.tcx.layout_of(param_ty).unwrap().size; - let literal = ConstantKind::from_bits(self.tcx, size.unsigned_int_max(), param_ty); + let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty); self.literal_operand(span, literal) } @@ -828,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = ConstantKind::from_bits(self.tcx, n, param_ty); + let literal = Const::from_bits(self.tcx, n, param_ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index c8910c272b1bb..a4ab365fa9a70 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -52,12 +52,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_info = match expr.kind { ExprKind::StaticRef { def_id, .. } => { assert!(!this.tcx.is_thread_local_static(def_id)); - local_decl.internal = true; LocalInfo::StaticRef { def_id, is_thread_local: false } } ExprKind::ThreadLocalRef(def_id) => { assert!(this.tcx.is_thread_local_static(def_id)); - local_decl.internal = true; LocalInfo::StaticRef { def_id, is_thread_local: true } } ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 1e0a47ead8c5c..a4de42d45c995 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -114,10 +114,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { true_block, source_info, destination, - Constant { + ConstOperand { span: expr_span, user_ty: None, - literal: ConstantKind::from_bool(this.tcx, true), + const_: Const::from_bool(this.tcx, true), }, ); @@ -125,10 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { false_block, source_info, destination, - Constant { + ConstOperand { span: expr_span, user_ty: None, - literal: ConstantKind::from_bool(this.tcx, false), + const_: Const::from_bool(this.tcx, false), }, ); @@ -186,10 +186,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { short_circuit, source_info, destination, - Constant { + ConstOperand { span: expr.span, user_ty: None, - literal: ConstantKind::from_bool(this.tcx, constant), + const_: Const::from_bool(this.tcx, constant), }, ); let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs])); @@ -433,12 +433,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } thir::InlineAsmOperand::Const { value, span } => { mir::InlineAsmOperand::Const { - value: Box::new(Constant { span, user_ty: None, literal: value }), + value: Box::new(ConstOperand { + span, + user_ty: None, + const_: value, + }), } } thir::InlineAsmOperand::SymFn { value, span } => { mir::InlineAsmOperand::SymFn { - value: Box::new(Constant { span, user_ty: None, literal: value }), + value: Box::new(ConstOperand { + span, + user_ty: None, + const_: value, + }), } } thir::InlineAsmOperand::SymStatic { def_id } => { diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index f5ae060d603f6..dfe85b858cd0d 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -44,7 +44,7 @@ //! the most suitable spot to implement it, and then just let the //! other fns cycle around. The handoff works like this: //! -//! - `into(place)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `place` +//! - `into(place)` -> fallback is to create an rvalue with `as_rvalue` and assign it to `place` //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use` //! - `as_operand` -> either invokes `as_constant` or `as_temp` //! - `as_constant` -> (no fallback) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 7e81c8b50c2d0..eb1c6a9824a47 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1005,13 +1005,13 @@ enum TestKind<'tcx> { /// /// For `bool` we always generate two edges, one for `true` and one for /// `false`. - options: FxIndexMap, u128>, + options: FxIndexMap, u128>, }, /// Test for equality with value, possibly after an unsizing coercion to /// `ty`, Eq { - value: ConstantKind<'tcx>, + value: Const<'tcx>, // Integer types are handled by `SwitchInt`, and constants with ADT // types are converted back into patterns, so this can only be `&str`, // `&[T]`, `f32` or `f64`. @@ -1622,9 +1622,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // may want to add cases based on the candidates that are // available match test.kind { - TestKind::SwitchInt { switch_ty, ref mut options } => { + TestKind::SwitchInt { switch_ty: _, ref mut options } => { for candidate in candidates.iter() { - if !self.add_cases_to_switch(&match_place, candidate, switch_ty, options) { + if !self.add_cases_to_switch(&match_place, candidate, options) { break; } } @@ -1798,7 +1798,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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)); let fake_borrow_temp = self.local_decls.push(fake_borrow_temp); @@ -2268,7 +2267,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty: var_ty, user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) }, source_info, - internal: false, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var( VarBindingForm { binding_mode, @@ -2298,7 +2296,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty: Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, var_ty), user_ty: None, source_info, - internal: false, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User( BindingForm::RefForGuard, ))), diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 484e8490919d4..795d1db8eecda 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -85,8 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, test_place: &PlaceBuilder<'tcx>, candidate: &Candidate<'pat, 'tcx>, - switch_ty: Ty<'tcx>, - options: &mut FxIndexMap, u128>, + options: &mut FxIndexMap, u128>, ) -> bool { let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else { @@ -95,9 +94,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match match_pair.pattern.kind { PatKind::Constant { value } => { - options - .entry(value) - .or_insert_with(|| value.eval_bits(self.tcx, self.param_env, switch_ty)); + options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env)); true } PatKind::Variant { .. } => { @@ -255,10 +252,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, TerminatorKind::Call { - func: Operand::Constant(Box::new(Constant { + func: Operand::Constant(Box::new(ConstOperand { span: test.span, user_ty: None, - literal: method, + const_: method, })), args: vec![Operand::Move(ref_string)], destination: ref_str, @@ -388,7 +385,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, make_target_blocks: impl FnOnce(&mut Self) -> Vec, source_info: SourceInfo, - value: ConstantKind<'tcx>, + value: Const<'tcx>, mut val: Place<'tcx>, mut ty: Ty<'tcx>, ) { @@ -485,7 +482,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, TerminatorKind::Call { - func: Operand::Constant(Box::new(Constant { + func: Operand::Constant(Box::new(ConstOperand { span: source_info.span, // FIXME(#54571): This constant comes from user input (a @@ -494,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Need to experiment. user_ty: None, - literal: method, + const_: method, })), args: vec![Operand::Copy(val), expect], destination: eq_result, @@ -800,11 +797,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern) } - fn const_range_contains( - &self, - range: &PatRange<'tcx>, - value: ConstantKind<'tcx>, - ) -> Option { + fn const_range_contains(&self, range: &PatRange<'tcx>, value: Const<'tcx>) -> Option { use std::cmp::Ordering::*; // For performance, it's important to only do the second @@ -821,7 +814,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn values_not_contained_in_range( &self, range: &PatRange<'tcx>, - options: &FxIndexMap, u128>, + options: &FxIndexMap, u128>, ) -> Option { for &val in options.keys() { if self.const_range_contains(range, val)? { @@ -866,7 +859,7 @@ fn trait_method<'tcx>( trait_def_id: DefId, method_name: Symbol, args: impl IntoIterator>>, -) -> ConstantKind<'tcx> { +) -> Const<'tcx> { // The unhygienic comparison here is acceptable because this is only // used on known traits. let item = tcx @@ -877,5 +870,5 @@ fn trait_method<'tcx>( let method_ty = Ty::new_fn_def(tcx, item.def_id, args); - ConstantKind::zero_sized(method_ty) + Const::zero_sized(method_ty) } diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 90d78658f9683..c263de79c3b84 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -15,9 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// N.B., **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. pub(crate) fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> { - // Mark this local as internal to avoid temporaries with types not present in the - // user's code resulting in ICEs from the generator transform. - let temp = self.local_decls.push(LocalDecl::new(ty, span).internal()); + let temp = self.local_decls.push(LocalDecl::new(ty, span)); let place = Place::from(temp); debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty); place @@ -25,19 +23,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Convenience function for creating a literal operand, one /// without any user type annotation. - pub(crate) fn literal_operand( - &mut self, - span: Span, - literal: ConstantKind<'tcx>, - ) -> Operand<'tcx> { - let constant = Box::new(Constant { span, user_ty: None, literal }); + pub(crate) fn literal_operand(&mut self, span: Span, const_: Const<'tcx>) -> Operand<'tcx> { + let constant = Box::new(ConstOperand { span, user_ty: None, const_ }); Operand::Constant(constant) } /// Returns a zero literal operand for the appropriate type, works for /// bool, char and integers. pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = ConstantKind::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); + let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); self.literal_operand(span, literal) } @@ -54,10 +48,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, temp, - Constant { + ConstOperand { span: source_info.span, user_ty: None, - literal: ConstantKind::from_usize(self.tcx, value), + const_: Const::from_usize(self.tcx, value), }, ); temp diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 7748ffab79ccf..bba47056457d3 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -633,7 +633,7 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo _ => bug!("expected closure or generator, found {ty:?}"), } } - hir::BodyOwnerKind::Const => 0, + hir::BodyOwnerKind::Const { .. } => 0, hir::BodyOwnerKind::Static(_) => 0, }; let mut cfg = CFG { basic_blocks: IndexVec::new() }; @@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Constants always need overflow checks. check_overflow |= matches!( tcx.hir().body_owner_kind(def), - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) + hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) ); let lint_level = LintLevel::Explicit(hir_id); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 4cf6a349af76c..bc151cc705898 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -725,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(Ty::new_unit(self.tcx), span).internal(); + let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span); 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/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3ff3387a78114..bee5ac550ddce 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -748,6 +748,12 @@ pub struct NontrivialStructuralMatch<'tcx> { pub non_sm_ty: Ty<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(mir_build_non_partial_eq_match)] +pub struct NonPartialEqMatch<'tcx> { + pub non_peq_ty: Ty<'tcx>, +} + #[derive(LintDiagnostic)] #[diag(mir_build_overlapping_range_endpoints)] #[note] diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 18b0e9a643e8a..16a85d4276177 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -647,21 +647,15 @@ impl<'tcx> Cx<'tcx> { out_expr: out_expr.map(|expr| self.mirror_expr(expr)), }, hir::InlineAsmOperand::Const { ref anon_const } => { - let value = mir::ConstantKind::from_anon_const( - tcx, - anon_const.def_id, - self.param_env, - ); + let value = + mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = mir::ConstantKind::from_anon_const( - tcx, - anon_const.def_id, - self.param_env, - ); + let value = + mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::SymFn { value, span } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 95dced644e161..d440ca319260c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -740,9 +740,7 @@ fn non_exhaustive_match<'p, 'tcx>( )); } } else if ty == cx.tcx.types.str_ { - err.note(format!( - "`&str` cannot be matched exhaustively, so a wildcard `_` is necessary", - )); + err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary"); } else if cx.is_foreign_non_exhaustive_enum(ty) { err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively")); } 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 1376344cfdaea..ae44246602996 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 @@ -16,18 +16,20 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch, - PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, + NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// Converts an evaluated constant to a pattern (if possible). /// This means aggregate values (like structs and enums) are converted /// to a pattern that matches the value (as if you'd compared via structural equality). + /// + /// `cv` must be a valtree or a `mir::ConstValue`. #[instrument(level = "debug", skip(self), ret)] pub(super) fn const_to_pat( &self, - cv: mir::ConstantKind<'tcx>, + cv: mir::Const<'tcx>, id: hir::HirId, span: Span, check_body_for_struct_match_violation: Option, @@ -64,12 +66,10 @@ struct ConstToPat<'tcx> { } /// This error type signals that we encountered a non-struct-eq situation. -/// We bubble this up in order to get back to the reference destructuring and make that emit -/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq` -/// on such patterns (since that function takes a reference) and not have to jump through any -/// hoops to get a reference to the value. +/// We will fall back to calling `PartialEq::eq` on such patterns, +/// and exhaustiveness checking will consider them as matching nothing. #[derive(Debug)] -struct FallbackToConstRef; +struct FallbackToOpaqueConst; impl<'tcx> ConstToPat<'tcx> { fn new( @@ -104,7 +104,7 @@ impl<'tcx> ConstToPat<'tcx> { fn to_pat( &mut self, - cv: mir::ConstantKind<'tcx>, + cv: mir::Const<'tcx>, check_body_for_struct_match_violation: Option, ) -> Box> { trace!(self.treat_byte_string_as_slice); @@ -124,7 +124,7 @@ impl<'tcx> ConstToPat<'tcx> { debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); let inlined_const_as_pat = match cv { - mir::ConstantKind::Ty(c) => match c.kind() { + mir::Const::Ty(c) => match c.kind() { ty::ConstKind::Param(_) | ty::ConstKind::Infer(_) | ty::ConstKind::Bound(_, _) @@ -136,7 +136,7 @@ impl<'tcx> ConstToPat<'tcx> { } ty::ConstKind::Value(valtree) => self .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false)) - .unwrap_or_else(|_| { + .unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), @@ -144,10 +144,10 @@ impl<'tcx> ConstToPat<'tcx> { }) }), }, - mir::ConstantKind::Unevaluated(_, _) => { + mir::Const::Unevaluated(_, _) => { span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}") } - mir::ConstantKind::Val(_, _) => Box::new(Pat { + mir::Const::Val(_, _) => Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Constant { value: cv }, @@ -155,8 +155,9 @@ impl<'tcx> ConstToPat<'tcx> { }; if !self.saw_const_match_error.get() { - // If we were able to successfully convert the const to some pat, - // double-check that all types in the const implement `Structural`. + // If we were able to successfully convert the const to some pat (possibly with some + // lints, but no errors), double-check that all types in the const implement + // `Structural` and `PartialEq`. let structural = traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); @@ -178,7 +179,7 @@ impl<'tcx> ConstToPat<'tcx> { } if let Some(non_sm_ty) = structural { - if !self.type_may_have_partial_eq_impl(cv.ty()) { + if !self.type_has_partial_eq_impl(cv.ty()) { if let ty::Adt(def, ..) = non_sm_ty.kind() { if def.is_union() { let err = UnionPattern { span: self.span }; @@ -192,8 +193,10 @@ impl<'tcx> ConstToPat<'tcx> { } else { let err = InvalidPattern { span: self.span, non_sm_ty }; self.tcx().sess.emit_err(err); - return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild }); } + // All branches above emitted an error. Don't print any more lints. + // The pattern we return is irrelevant since we errored. + return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild }); } else if !self.saw_const_match_lint.get() { if let Some(mir_structural_match_violation) = mir_structural_match_violation { match non_sm_ty.kind() { @@ -238,13 +241,24 @@ impl<'tcx> ConstToPat<'tcx> { _ => {} } } + + // Always check for `PartialEq`, even if we emitted other lints. (But not if there were + // any errors.) This ensures it shows up in cargo's future-compat reports as well. + if !self.type_has_partial_eq_impl(cv.ty()) { + self.tcx().emit_spanned_lint( + lint::builtin::CONST_PATTERNS_WITHOUT_PARTIAL_EQ, + self.id, + self.span, + NonPartialEqMatch { non_peq_ty: cv.ty() }, + ); + } } inlined_const_as_pat } #[instrument(level = "trace", skip(self), ret)] - fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { + fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { // double-check there even *is* a semantic `PartialEq` to dispatch to. // // (If there isn't, then we can safely issue a hard @@ -259,14 +273,19 @@ impl<'tcx> ConstToPat<'tcx> { ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]), ); - // FIXME: should this call a `predicate_must_hold` variant instead? - self.infcx.predicate_may_hold(&partial_eq_obligation) + // This *could* accept a type that isn't actually `PartialEq`, because region bounds get + // ignored. However that should be pretty much impossible since consts that do not depend on + // generics can only mention the `'static` lifetime, and how would one have a type that's + // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem + // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck + // can ensure that the type really implements `PartialEq`. + self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) } fn field_pats( &self, vals: impl Iterator, Ty<'tcx>)>, - ) -> Result>, FallbackToConstRef> { + ) -> Result>, FallbackToOpaqueConst> { vals.enumerate() .map(|(idx, (val, ty))| { let field = FieldIdx::new(idx); @@ -284,7 +303,7 @@ impl<'tcx> ConstToPat<'tcx> { cv: ValTree<'tcx>, ty: Ty<'tcx>, mir_structural_match_violation: bool, - ) -> Result>, FallbackToConstRef> { + ) -> Result>, FallbackToOpaqueConst> { let id = self.id; let span = self.span; let tcx = self.tcx(); @@ -299,7 +318,7 @@ impl<'tcx> ConstToPat<'tcx> { span, FloatPattern, ); - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } // If the type is not structurally comparable, just emit the constant directly, // causing the pattern match code to treat it opaquely. @@ -323,11 +342,12 @@ impl<'tcx> ConstToPat<'tcx> { // Since we are behind a reference, we can just bubble the error up so we get a // constant at reference type, making it easy to let the fallback call // `PartialEq::eq` on it. - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } ty::FnDef(..) => { self.saw_const_match_error.set(true); tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty }); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { @@ -335,6 +355,7 @@ impl<'tcx> ConstToPat<'tcx> { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: ty }; tcx.sess.emit_err(err); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } ty::Adt(adt_def, args) if adt_def.is_enum() => { @@ -385,9 +406,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(ty::Const::new_value(tcx, cv, ty)), - }, + ty::Str => { + PatKind::Constant { value: mir::Const::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 @@ -404,13 +425,15 @@ impl<'tcx> ConstToPat<'tcx> { IndirectStructuralMatch { non_sm_ty: *pointee_ty }, ); } - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } else { if !self.saw_const_match_error.get() { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: *pointee_ty }; tcx.sess.emit_err(err); } + tcx.sess.delay_span_bug(span, "`saw_const_match_error` set but no error?"); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } } @@ -423,6 +446,7 @@ impl<'tcx> ConstToPat<'tcx> { tcx.sess.emit_err(err); // FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns. + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } else { let old = self.behind_reference.replace(true); @@ -445,14 +469,15 @@ impl<'tcx> ConstToPat<'tcx> { } } }, - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => PatKind::Constant { - value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), - }, + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => { + PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } + } ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), _ => { self.saw_const_match_error.set(true); let err = InvalidPattern { span, non_sm_ty: ty }; tcx.sess.emit_err(err); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index bee1c4e4614f4..3ee4befa12189 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -50,6 +50,7 @@ use std::ops::RangeInclusive; use smallvec::{smallvec, SmallVec}; +use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS}; use rustc_data_structures::captures::Captures; use rustc_hir::{HirId, RangeEnd}; use rustc_index::Idx; @@ -60,12 +61,11 @@ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use self::Constructor::*; use self::SliceKind::*; -use super::compare_const_vals; use super::usefulness::{MatchCheckCtxt, PatCtxt}; use crate::errors::{Overlap, OverlappingRangeEndpoints}; @@ -99,10 +99,6 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { #[derive(Clone, PartialEq, Eq)] pub(crate) struct IntRange { range: RangeInclusive, - /// Keeps the bias used for encoding the range. It depends on the type of the range and - /// possibly the pointer size of the current architecture. The algorithm ensures we never - /// compare `IntRange`s with different types/architectures. - bias: u128, } impl IntRange { @@ -120,37 +116,12 @@ impl IntRange { } #[inline] - fn integral_size_and_signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Size, u128)> { - match *ty.kind() { - ty::Bool => Some((Size::from_bytes(1), 0)), - ty::Char => Some((Size::from_bytes(4), 0)), - ty::Int(ity) => { - let size = Integer::from_int_ty(&tcx, ity).size(); - Some((size, 1u128 << (size.bits() as u128 - 1))) - } - ty::Uint(uty) => Some((Integer::from_uint_ty(&tcx, uty).size(), 0)), - _ => None, - } - } - - #[inline] - fn from_constant<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: mir::ConstantKind<'tcx>, - ) -> Option { - let ty = value.ty(); - let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?; - let val = match value { - mir::ConstantKind::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => { - valtree.unwrap_leaf().to_bits(target_size).ok() - }, - // This is a more general form of the previous case. - _ => value.try_eval_bits(tcx, param_env, ty), - }?; - - let val = val ^ bias; - Some(IntRange { range: val..=val, bias }) + fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange { + let bias = IntRange::signed_bias(tcx, ty); + // Perform a shift if the underlying types are signed, + // which makes the interval arithmetic simpler. + let val = bits ^ bias; + IntRange { range: val..=val } } #[inline] @@ -159,20 +130,18 @@ impl IntRange { lo: u128, hi: u128, ty: Ty<'tcx>, - end: &RangeEnd, - ) -> Option { - Self::is_integral(ty).then(|| { - // Perform a shift if the underlying types are signed, - // which makes the interval arithmetic simpler. - let bias = IntRange::signed_bias(tcx, ty); - let (lo, hi) = (lo ^ bias, hi ^ bias); - let offset = (*end == RangeEnd::Excluded) as u128; - if lo > hi || (lo == hi && *end == RangeEnd::Excluded) { - // This should have been caught earlier by E0030. - bug!("malformed range pattern: {}..={}", lo, (hi - offset)); - } - IntRange { range: lo..=(hi - offset), bias } - }) + end: RangeEnd, + ) -> IntRange { + // Perform a shift if the underlying types are signed, + // which makes the interval arithmetic simpler. + let bias = IntRange::signed_bias(tcx, ty); + let (lo, hi) = (lo ^ bias, hi ^ bias); + let offset = (end == RangeEnd::Excluded) as u128; + if lo > hi || (lo == hi && end == RangeEnd::Excluded) { + // This should have been caught earlier by E0030. + bug!("malformed range pattern: {}..={}", lo, (hi - offset)); + } + IntRange { range: lo..=(hi - offset) } } // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. @@ -194,7 +163,7 @@ impl IntRange { let (lo, hi) = self.boundaries(); let (other_lo, other_hi) = other.boundaries(); if lo <= other_hi && other_lo <= hi { - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), bias: self.bias }) + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) }) } else { None } @@ -221,12 +190,12 @@ impl IntRange { fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> { let (lo, hi) = self.boundaries(); - let bias = self.bias; + let bias = IntRange::signed_bias(tcx, ty); let (lo, hi) = (lo ^ bias, hi ^ bias); let env = ty::ParamEnv::empty().and(ty); - let lo_const = mir::ConstantKind::from_bits(tcx, lo, env); - let hi_const = mir::ConstantKind::from_bits(tcx, hi, env); + let lo_const = mir::Const::from_bits(tcx, lo, env); + let hi_const = mir::Const::from_bits(tcx, hi, env); let kind = if lo == hi { PatKind::Constant { value: lo_const } @@ -304,8 +273,6 @@ impl IntRange { impl fmt::Debug for IntRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (lo, hi) = self.boundaries(); - let bias = self.bias; - let (lo, hi) = (lo ^ bias, hi ^ bias); write!(f, "{lo}")?; write!(f, "{}", RangeEnd::Included)?; write!(f, "{hi}") @@ -402,7 +369,7 @@ impl SplitIntRange { (JustBefore(n), AfterMax) => n..=u128::MAX, _ => unreachable!(), // Ruled out by the sorting and filtering we did }; - IntRange { range, bias: self.range.bias } + IntRange { range } }) } } @@ -619,9 +586,10 @@ pub(super) enum Constructor<'tcx> { /// Ranges of integer literal values (`2`, `2..=5` or `2..5`). IntRange(IntRange), /// Ranges of floating-point literal values (`2.0..=5.2`). - FloatRange(mir::ConstantKind<'tcx>, mir::ConstantKind<'tcx>, RangeEnd), + F32Range(IeeeFloat, IeeeFloat, RangeEnd), + F64Range(IeeeFloat, IeeeFloat, RangeEnd), /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately. - Str(mir::ConstantKind<'tcx>), + Str(mir::Const<'tcx>), /// Array and slice patterns. Slice(Slice), /// Constants that must not be matched structurally. They are treated as black @@ -634,7 +602,9 @@ pub(super) enum Constructor<'tcx> { /// Stands for constructors that are not seen in the matrix, as explained in the documentation /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns` /// lint. - Missing { nonexhaustive_enum_missing_real_variants: bool }, + Missing { + nonexhaustive_enum_missing_real_variants: bool, + }, /// Wildcard pattern. Wildcard, /// Or-pattern. @@ -722,7 +692,8 @@ impl<'tcx> Constructor<'tcx> { }, Slice(slice) => slice.arity(), Str(..) - | FloatRange(..) + | F32Range(..) + | F64Range(..) | IntRange(..) | NonExhaustive | Opaque @@ -795,21 +766,21 @@ impl<'tcx> Constructor<'tcx> { (Variant(self_id), Variant(other_id)) => self_id == other_id, (IntRange(self_range), IntRange(other_range)) => self_range.is_covered_by(other_range), - ( - FloatRange(self_from, self_to, self_end), - FloatRange(other_from, other_to, other_end), - ) => { - match ( - compare_const_vals(pcx.cx.tcx, *self_to, *other_to, pcx.cx.param_env), - compare_const_vals(pcx.cx.tcx, *self_from, *other_from, pcx.cx.param_env), - ) { - (Some(to), Some(from)) => { - (from == Ordering::Greater || from == Ordering::Equal) - && (to == Ordering::Less - || (other_end == self_end && to == Ordering::Equal)) + (F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => { + self_from.ge(other_from) + && match self_to.partial_cmp(other_to) { + Some(Ordering::Less) => true, + Some(Ordering::Equal) => other_end == self_end, + _ => false, + } + } + (F64Range(self_from, self_to, self_end), F64Range(other_from, other_to, other_end)) => { + self_from.ge(other_from) + && match self_to.partial_cmp(other_to) { + Some(Ordering::Less) => true, + Some(Ordering::Equal) => other_end == self_end, + _ => false, } - _ => false, - } } (Str(self_val), Str(other_val)) => { // FIXME Once valtrees are available we can directly use the bytes @@ -859,7 +830,7 @@ impl<'tcx> Constructor<'tcx> { .any(|other| slice.is_covered_by(other)), // This constructor is never covered by anything else NonExhaustive => false, - Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard | Or => { + Str(..) | F32Range(..) | F64Range(..) | Opaque | Missing { .. } | Wildcard | Or => { span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self) } } @@ -896,7 +867,7 @@ impl<'tcx> SplitWildcard<'tcx> { let make_range = |start, end| { IntRange( // `unwrap()` is ok because we know the type is an integer. - IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included).unwrap(), + IntRange::from_range(cx.tcx, start, end, pcx.ty, RangeEnd::Included), ) }; // This determines the set of all possible constructors for the type `pcx.ty`. For numbers, @@ -1203,7 +1174,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { _ => bug!("bad slice pattern {:?} {:?}", constructor, pcx), }, Str(..) - | FloatRange(..) + | F32Range(..) + | F64Range(..) | IntRange(..) | NonExhaustive | Opaque @@ -1343,50 +1315,78 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } } PatKind::Constant { value } => { - if let Some(int_range) = IntRange::from_constant(cx.tcx, cx.param_env, *value) { - ctor = IntRange(int_range); - fields = Fields::empty(); - } else { - match pat.ty.kind() { - ty::Float(_) => { - ctor = FloatRange(*value, *value, RangeEnd::Included); - fields = Fields::empty(); - } - ty::Ref(_, t, _) if t.is_str() => { - // We want a `&str` constant to behave like a `Deref` pattern, to be compatible - // with other `Deref` patterns. This could have been done in `const_to_pat`, - // but that causes issues with the rest of the matching code. - // So here, the constructor for a `"foo"` pattern is `&` (represented by - // `Single`), and has one field. That field has constructor `Str(value)` and no - // fields. - // Note: `t` is `str`, not `&str`. - let subpattern = - DeconstructedPat::new(Str(*value), Fields::empty(), *t, pat.span); - ctor = Single; - fields = Fields::singleton(cx, subpattern) - } - // All constants that can be structurally matched have already been expanded - // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are - // opaque. - _ => { - ctor = Opaque; - fields = Fields::empty(); - } + match pat.ty.kind() { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => { + ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)), + None => Opaque, + }; + fields = Fields::empty(); + } + ty::Float(ty::FloatTy::F32) => { + ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + Some(bits) => { + use rustc_apfloat::Float; + let value = rustc_apfloat::ieee::Single::from_bits(bits); + F32Range(value, value, RangeEnd::Included) + } + None => Opaque, + }; + fields = Fields::empty(); + } + ty::Float(ty::FloatTy::F64) => { + ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + Some(bits) => { + use rustc_apfloat::Float; + let value = rustc_apfloat::ieee::Double::from_bits(bits); + F64Range(value, value, RangeEnd::Included) + } + None => Opaque, + }; + fields = Fields::empty(); + } + ty::Ref(_, t, _) if t.is_str() => { + // We want a `&str` constant to behave like a `Deref` pattern, to be compatible + // with other `Deref` patterns. This could have been done in `const_to_pat`, + // but that causes issues with the rest of the matching code. + // So here, the constructor for a `"foo"` pattern is `&` (represented by + // `Single`), and has one field. That field has constructor `Str(value)` and no + // fields. + // Note: `t` is `str`, not `&str`. + let subpattern = + DeconstructedPat::new(Str(*value), Fields::empty(), *t, pat.span); + ctor = Single; + fields = Fields::singleton(cx, subpattern) + } + // All constants that can be structurally matched have already been expanded + // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are + // opaque. + _ => { + ctor = Opaque; + fields = Fields::empty(); } } } - &PatKind::Range(box PatRange { lo, hi, end }) => { + PatKind::Range(box PatRange { lo, hi, end }) => { + use rustc_apfloat::Float; let ty = lo.ty(); - ctor = if let Some(int_range) = IntRange::from_range( - cx.tcx, - lo.eval_bits(cx.tcx, cx.param_env, lo.ty()), - hi.eval_bits(cx.tcx, cx.param_env, hi.ty()), - ty, - &end, - ) { - IntRange(int_range) - } else { - FloatRange(lo, hi, end) + let lo = lo.try_eval_bits(cx.tcx, cx.param_env).unwrap(); + let hi = hi.try_eval_bits(cx.tcx, cx.param_env).unwrap(); + ctor = match ty.kind() { + ty::Char | ty::Int(_) | ty::Uint(_) => { + IntRange(IntRange::from_range(cx.tcx, lo, hi, ty, *end)) + } + ty::Float(ty::FloatTy::F32) => { + let lo = rustc_apfloat::ieee::Single::from_bits(lo); + let hi = rustc_apfloat::ieee::Single::from_bits(hi); + F32Range(lo, hi, *end) + } + ty::Float(ty::FloatTy::F64) => { + let lo = rustc_apfloat::ieee::Double::from_bits(lo); + let hi = rustc_apfloat::ieee::Double::from_bits(hi); + F64Range(lo, hi, *end) + } + _ => bug!("invalid type for range pattern: {}", ty), }; fields = Fields::empty(); } @@ -1491,14 +1491,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } } &Str(value) => PatKind::Constant { value }, - &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })), IntRange(range) => return range.to_pat(cx.tcx, self.ty), Wildcard | NonExhaustive => PatKind::Wild, Missing { .. } => bug!( "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug, `Missing` should have been processed in `apply_constructors`" ), - Opaque | Or => { + F32Range(..) | F64Range(..) | Opaque | Or => { bug!("can't convert to pattern: {:?}", self) } }; @@ -1673,11 +1672,8 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { } write!(f, "]") } - &FloatRange(lo, hi, end) => { - write!(f, "{lo}")?; - write!(f, "{end}")?; - write!(f, "{hi}") - } + F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), + F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), IntRange(range) => write!(f, "{range:?}"), // Best-effort, will render e.g. `false` as `0..=0` Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty), Or => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3d9e634c84931..fe47a1cd78c49 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -20,7 +20,7 @@ use rustc_index::Idx; use rustc_middle::mir::interpret::{ ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar, }; -use rustc_middle::mir::{self, ConstantKind, UserTypeProjection}; +use rustc_middle::mir::{self, Const, UserTypeProjection}; use rustc_middle::mir::{BorrowKind, Mutability}; use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; use rustc_middle::ty::CanonicalUserTypeAnnotation; @@ -100,8 +100,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range( &mut self, ty: Ty<'tcx>, - lo: mir::ConstantKind<'tcx>, - hi: mir::ConstantKind<'tcx>, + lo: mir::Const<'tcx>, + hi: mir::Const<'tcx>, end: RangeEnd, span: Span, lo_expr: Option<&hir::Expr<'tcx>>, @@ -131,7 +131,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr && let rustc_ast::ast::LitKind::Int(val, _) = lit.node { - if lo.eval_bits(self.tcx, self.param_env, ty) != val { + if lo.eval_bits(self.tcx, self.param_env) != val { lower_overflow = true; self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); } @@ -139,7 +139,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr && let rustc_ast::ast::LitKind::Int(val, _) = lit.node { - if hi.eval_bits(self.tcx, self.param_env, ty) != val { + if hi.eval_bits(self.tcx, self.param_env) != val { higher_overflow = true; self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); } @@ -162,7 +162,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr && let rustc_ast::ast::LitKind::Int(val, _) = lit.node { - if lo.eval_bits(self.tcx, self.param_env, ty) != val { + if lo.eval_bits(self.tcx, self.param_env) != val { lower_overflow = true; self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); } @@ -170,7 +170,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr && let rustc_ast::ast::LitKind::Int(val, _) = lit.node { - if hi.eval_bits(self.tcx, self.param_env, ty) != val { + if hi.eval_bits(self.tcx, self.param_env) != val { higher_overflow = true; self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); } @@ -191,18 +191,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ty: Ty<'tcx>, lo: Option<&PatKind<'tcx>>, hi: Option<&PatKind<'tcx>>, - ) -> Option<(mir::ConstantKind<'tcx>, mir::ConstantKind<'tcx>)> { + ) -> Option<(mir::Const<'tcx>, mir::Const<'tcx>)> { match (lo, hi) { (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => { Some((*lo, *hi)) } (Some(PatKind::Constant { value: lo }), None) => { let hi = ty.numeric_max_val(self.tcx)?; - Some((*lo, mir::ConstantKind::from_ty_const(hi, self.tcx))) + Some((*lo, mir::Const::from_ty_const(hi, self.tcx))) } (None, Some(PatKind::Constant { value: hi })) => { let lo = ty.numeric_min_val(self.tcx)?; - Some((mir::ConstantKind::from_ty_const(lo, self.tcx), *hi)) + Some((mir::Const::from_ty_const(lo, self.tcx), *hi)) } _ => None, } @@ -439,7 +439,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { DefKind::Struct | DefKind::Ctor(CtorOf::Struct, ..) | DefKind::Union - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy, _, ) @@ -525,8 +525,8 @@ 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(ty::Const::new_value(self.tcx, valtree, ty)), - None => mir::ConstantKind::Val( + Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), + None => mir::Const::Val( self.tcx .const_eval_global_id(param_env_reveal_all, cid, Some(span)) .expect("const_eval_global_id_for_typeck should have already failed"), @@ -608,7 +608,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind, + Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -632,7 +632,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { self.const_to_pat( - ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)), + Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span, None, @@ -641,7 +641,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { - Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind, + Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind, Err(ErrorHandled::TooGeneric(_)) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); @@ -678,7 +678,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { Ok(constant) => { - self.const_to_pat(ConstantKind::Ty(constant), expr.hir_id, lit.span, None).kind + self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind } Err(LitToConstError::Reported(_)) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), @@ -838,8 +838,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { #[instrument(skip(tcx), level = "debug")] pub(crate) fn compare_const_vals<'tcx>( tcx: TyCtxt<'tcx>, - a: mir::ConstantKind<'tcx>, - b: mir::ConstantKind<'tcx>, + a: mir::Const<'tcx>, + b: mir::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option { assert_eq!(a.ty(), b.ty()); @@ -855,18 +855,18 @@ pub(crate) fn compare_const_vals<'tcx>( ty::Float(_) | ty::Int(_) => {} // require special handling, see below _ => match (a, b) { ( - mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty), - mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _b_ty), + mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty), + mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _b_ty), ) => return Some(a.cmp(&b)), - (mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => { + (mir::Const::Ty(a), mir::Const::Ty(b)) => { return Some(a.kind().cmp(&b.kind())); } _ => {} }, } - let a = a.eval_bits(tcx, param_env, ty); - let b = b.eval_bits(tcx, param_env, ty); + let a = a.eval_bits(tcx, param_env); + let b = b.eval_bits(tcx, param_env); use rustc_apfloat::Float; match *ty.kind() { diff --git a/compiler/rustc_mir_dataflow/src/debuginfo.rs b/compiler/rustc_mir_dataflow/src/debuginfo.rs new file mode 100644 index 0000000000000..fd5e8cf295552 --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/debuginfo.rs @@ -0,0 +1,20 @@ +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; + +/// Return the set of locals that appear in debuginfo. +pub fn debuginfo_locals(body: &Body<'_>) -> BitSet { + let mut visitor = DebuginfoLocals(BitSet::new_empty(body.local_decls.len())); + for debuginfo in body.var_debug_info.iter() { + visitor.visit_var_debug_info(debuginfo); + } + visitor.0 +} + +struct DebuginfoLocals(BitSet); + +impl Visitor<'_> for DebuginfoLocals { + fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) { + self.0.insert(local); + } +} diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index ad5f83d9e25e5..c9991e499b32a 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -194,6 +194,7 @@ where D: DropElaborator<'b, 'tcx>, 'tcx: 'b, { + #[instrument(level = "trace", skip(self), ret)] fn place_ty(&self, place: Place<'tcx>) -> Ty<'tcx> { place.ty(self.elaborator.body(), self.tcx()).ty } @@ -220,11 +221,9 @@ where // // FIXME: I think we should just control the flags externally, // and then we do not need this machinery. + #[instrument(level = "debug")] pub fn elaborate_drop(&mut self, bb: BasicBlock) { - debug!("elaborate_drop({:?}, {:?})", bb, self); - let style = self.elaborator.drop_style(self.path, DropFlagMode::Deep); - debug!("elaborate_drop({:?}, {:?}): live - {:?}", bb, self, style); - match style { + match self.elaborator.drop_style(self.path, DropFlagMode::Deep) { DropStyle::Dead => { self.elaborator .patch() @@ -973,10 +972,10 @@ where } fn constant_usize(&self, val: u16) -> Operand<'tcx> { - Operand::Constant(Box::new(Constant { + Operand::Constant(Box::new(ConstOperand { span: self.source_info.span, user_ty: None, - literal: ConstantKind::from_usize(self.tcx(), val.into()), + const_: Const::from_usize(self.tcx(), val.into()), })) } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 0cdbee19d2c80..ecf46715cd088 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -35,6 +35,7 @@ pub use self::framework::{ use self::move_paths::MoveData; +pub mod debuginfo; pub mod drop_flag_effects; pub mod elaborate_drops; mod errors; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs index 7806e8f45d3ad..2a7f23ef6d251 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs @@ -57,6 +57,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> { ProjectionElem::ConstantIndex { offset, min_length, from_end } } ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u), + ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty.lift()), } } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 2e3b9577b5030..7a5b3585d5971 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -115,44 +115,126 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let body = self.builder.body; let tcx = self.builder.tcx; let place_ty = place_ref.ty(body, tcx).ty; - match place_ty.kind() { - ty::Ref(..) | ty::RawPtr(..) => { - return Err(MoveError::cannot_move_out_of( - self.loc, - BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) }, - )); - } - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfTypeWithDestructor { container_ty: place_ty }, - )); - } - ty::Adt(adt, _) if adt.is_union() => { - union_path.get_or_insert(base); - } - ty::Slice(_) => { - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { - ty: place_ty, - is_index: matches!(elem, ProjectionElem::Index(..)), - }, - )); + match elem { + ProjectionElem::Deref => match place_ty.kind() { + ty::Ref(..) | ty::RawPtr(..) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + BorrowedContent { + target_place: place_ref.project_deeper(&[elem], tcx), + }, + )); + } + ty::Adt(adt, _) => { + if !adt.is_box() { + bug!("Adt should be a box type when Place is deref"); + } + } + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::Generator(_, _, _) + | ty::GeneratorWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Infer(_) + | ty::Error(_) + | ty::Placeholder(_) => { + bug!("When Place is Deref it's type shouldn't be {place_ty:#?}") + } + }, + ProjectionElem::Field(_, _) => match place_ty.kind() { + ty::Adt(adt, _) => { + if adt.has_dtor(tcx) { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfTypeWithDestructor { container_ty: place_ty }, + )); + } + if adt.is_union() { + union_path.get_or_insert(base); + } + } + ty::Closure(_, _) | ty::Generator(_, _, _) | ty::Tuple(_) => (), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _, _) + | ty::GeneratorWitness(..) + | ty::Never + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Infer(_) + | ty::Error(_) + | ty::Placeholder(_) => bug!( + "When Place contains ProjectionElem::Field it's type shouldn't be {place_ty:#?}" + ), + }, + ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { + match place_ty.kind() { + ty::Slice(_) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, + is_index: matches!(elem, ProjectionElem::Index(..)), + }, + )); + } + ty::Array(_, _) => (), + _ => bug!("Unexpected type {:#?}", place_ty.is_array()), + } } - - ty::Array(..) => { - if let ProjectionElem::Index(..) = elem { + ProjectionElem::Index(_) => match place_ty.kind() { + ty::Array(..) => { return Err(MoveError::cannot_move_out_of( self.loc, InteriorOfSliceOrArray { ty: place_ty, is_index: true }, )); } - } - - _ => {} - }; - + ty::Slice(_) => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, + is_index: matches!(elem, ProjectionElem::Index(..)), + }, + )); + } + _ => bug!("Unexpected type {place_ty:#?}"), + }, + // `OpaqueCast`:Only transmutes the type, so no moves there. + // `Downcast` :Only changes information about a `Place` without moving. + // `Subtype` :Only transmutes the type, so moves. + // So it's safe to skip these. + ProjectionElem::OpaqueCast(_) + | ProjectionElem::Subtype(_) + | ProjectionElem::Downcast(_, _) => (), + } if union_path.is_none() { // inlined from add_move_path because of a borrowck conflict with the iterator base = diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 775c522b476f6..1ebb59b3a637f 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -190,7 +190,7 @@ impl PeekCall { if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } = &terminator.kind { - if let ty::FnDef(def_id, fn_args) = *func.literal.ty().kind() { + if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() { let name = tcx.item_name(def_id); if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek { return None; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 514146b503013..83766f31148b1 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -225,7 +225,7 @@ pub trait ValueAnalysis<'tcx> { fn handle_constant( &self, - constant: &Constant<'tcx>, + constant: &ConstOperand<'tcx>, state: &mut State, ) -> Self::Value { self.super_constant(constant, state) @@ -233,7 +233,7 @@ pub trait ValueAnalysis<'tcx> { fn super_constant( &self, - _constant: &Constant<'tcx>, + _constant: &ConstOperand<'tcx>, _state: &mut State, ) -> Self::Value { Self::Value::TOP @@ -758,7 +758,9 @@ impl Map { self.value_count += 1; } - if let Some(ref_ty) = ty.builtin_deref(true) && let ty::Slice(..) = ref_ty.ty.kind() { + if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ty::TypeAndMut { ty: ref_ty, .. }) = ty.kind() + && let ty::Slice(..) = ref_ty.kind() + { assert!(self.places[place].value_index.is_none(), "slices are not scalars"); // Prepend new child to the linked list. diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs new file mode 100644 index 0000000000000..e5be7c0ca76e2 --- /dev/null +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -0,0 +1,70 @@ +use crate::MirPass; +use rustc_index::IndexVec; +use rustc_middle::mir::patch::MirPatch; +use rustc_middle::mir::visit::MutVisitor; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +pub struct Subtyper; + +pub struct SubTypeChecker<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + patcher: MirPatch<'tcx>, + local_decls: &'a IndexVec>, +} + +impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_assign( + &mut self, + place: &mut Place<'tcx>, + rvalue: &mut Rvalue<'tcx>, + location: Location, + ) { + // We don't need to do anything for deref temps as they are + // not part of the source code, but used for desugaring purposes. + if self.local_decls[place.local].is_deref_temp() { + return; + } + let mut place_ty = place.ty(self.local_decls, self.tcx).ty; + let mut rval_ty = rvalue.ty(self.local_decls, self.tcx); + // Not erasing this causes `Free Regions` errors in validator, + // when rval is `ReStatic`. + rval_ty = self.tcx.erase_regions_ty(rval_ty); + place_ty = self.tcx.erase_regions(place_ty); + if place_ty != rval_ty { + let temp = self + .patcher + .new_temp(rval_ty, self.local_decls[place.as_ref().local].source_info.span); + let new_place = Place::from(temp); + self.patcher.add_assign(location, new_place, rvalue.clone()); + let subtyped = new_place.project_deeper(&[ProjectionElem::Subtype(place_ty)], self.tcx); + *rvalue = Rvalue::Use(Operand::Move(subtyped)); + } + } +} + +// Aim here is to do this kind of transformation: +// +// let place: place_ty = rval; +// // gets transformed to +// let temp: rval_ty = rval; +// let place: place_ty = temp as place_ty; +pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let patch = MirPatch::new(body); + let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; + + for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + checker.visit_basic_block_data(bb, data); + } + checker.patcher.apply(body); +} + +impl<'tcx> MirPass<'tcx> for Subtyper { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + subtype_finder(tcx, body); + } +} diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index fe66a9a09946a..28765af20ad3b 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -181,13 +181,10 @@ fn insert_alignment_check<'tcx>( // Subtract 1 from the alignment to get the alignment mask let alignment_mask = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - let one = Operand::Constant(Box::new(Constant { + let one = Operand::Constant(Box::new(ConstOperand { span: source_info.span, user_ty: None, - literal: ConstantKind::Val( - ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), - tcx.types.usize, - ), + const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize), })); block_data.statements.push(Statement { source_info, @@ -213,13 +210,10 @@ fn insert_alignment_check<'tcx>( // Check if the alignment bits are all zero let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - let zero = Operand::Constant(Box::new(Constant { + let zero = Operand::Constant(Box::new(ConstOperand { span: source_info.span, user_ty: None, - literal: ConstantKind::Val( - ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), - tcx.types.usize, - ), + const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize), })); block_data.statements.push(Statement { source_info, diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d5af321d72639..c428007707eeb 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -142,9 +142,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) { if let Operand::Constant(constant) = op { - let maybe_uneval = match constant.literal { - ConstantKind::Val(..) | ConstantKind::Ty(_) => None, - ConstantKind::Unevaluated(uv, _) => Some(uv), + let maybe_uneval = match constant.const_ { + Const::Val(..) | Const::Ty(_) => None, + Const::Unevaluated(uv, _) => Some(uv), }; if let Some(uv) = maybe_uneval { @@ -179,7 +179,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { // Check the base local: it might be an unsafe-to-access static. We only check derefs of the // temporary holding the static pointer to avoid duplicate errors // . - if decl.internal && place.projection.first() == Some(&ProjectionElem::Deref) { + if place.projection.first() == Some(&ProjectionElem::Deref) { // If the projection root is an artificial local that we introduced when // desugaring `static`, give a more specific error message // (avoid the general "raw pointer" clause below, that would only be confusing). diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs index f662ce645b08d..40cd2825408d4 100644 --- a/compiler/rustc_mir_transform/src/const_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs @@ -4,7 +4,7 @@ use rustc_middle::{ mir::{ visit::{PlaceContext, Visitor}, - Body, Constant, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents, + Body, ConstOperand, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents, }, ty::TyCtxt, }; @@ -45,7 +45,7 @@ struct LocalUseVisitor { local_assignment_locations: IndexVec>, } -fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> { +fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, ConstOperand<'tcx>)> { let mut visitor = LocalUseVisitor { local_mutating_uses: IndexVec::from_elem(0, &body.local_decls), local_assignment_locations: IndexVec::from_elem(None, &body.local_decls), diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index e175f22d7a940..fd2d37dbea518 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -96,10 +96,10 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { let (discr, targets) = target_bb_terminator.kind.as_switch()?; if discr.place() == Some(*place) { let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty; + debug_assert_eq!(switch_ty, _const.ty()); // We now know that the Switch matches on the const place, and it is statementless // Now find which value in the Switch matches the const value. - let const_value = - _const.literal.try_eval_bits(self.tcx, self.param_env, switch_ty)?; + let const_value = _const.const_.try_eval_bits(self.tcx, self.param_env)?; let target_to_use_in_goto = targets.target_for_value(const_value); self.optimizations.push(OptimizationToApply { bb_with_goto: location.block, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index c6aac2ca21339..4fc78b285803d 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -210,7 +210,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> _bin_op: BinOp, _left: &ImmTy<'tcx>, _right: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx>, bool)> { // We can't do this because aliasing of memory can differ between const eval and llvm throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } @@ -525,7 +525,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn replace_with_const(&mut self, place: Place<'tcx>) -> Option> { + fn replace_with_const(&mut self, place: Place<'tcx>) -> Option> { // This will return None if the above `const_prop` invocation only "wrote" a // type whose creation requires no write. E.g. a generator whose initial state // consists solely of uninitialized memory (so it doesn't capture any locals). @@ -541,7 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let Right(imm) = imm else { return None }; match *imm { Immediate::Scalar(scalar) if scalar.try_to_int().is_ok() => { - Some(ConstantKind::from_scalar(self.tcx, scalar, value.layout.ty)) + Some(Const::from_scalar(self.tcx, scalar, value.layout.ty)) } Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => { let alloc_id = self @@ -551,7 +551,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }) .ok()?; - Some(ConstantKind::Val( + Some(Const::Val( ConstValue::Indirect { alloc_id, offset: Size::ZERO }, value.layout.ty, )) @@ -731,7 +731,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { if let Some(()) = self.eval_rvalue_with_identities(rvalue, *place) { // If this was already an evaluated constant, keep it. if let Rvalue::Use(Operand::Constant(c)) = rvalue - && let ConstantKind::Val(..) = c.literal + && let Const::Val(..) = c.const_ { trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c); } else if let Some(operand) = self.replace_with_const(*place) { diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index fb33b3b49d30c..64e262c6c9359 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -281,7 +281,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } /// Returns the value, if any, of evaluating `c`. - fn eval_constant(&mut self, c: &Constant<'tcx>, location: Location) -> Option> { + fn eval_constant(&mut self, c: &ConstOperand<'tcx>, location: Location) -> Option> { // FIXME we need to revisit this for #67176 if c.has_param() { return None; @@ -293,7 +293,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // that the `RevealAll` pass has happened and that the body's consts // are normalized, so any call to resolve before that needs to be // manually normalized. - let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?; + let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?; self.use_ecx(location, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None)) } @@ -322,7 +322,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>, location: Location) -> Option<()> { if let (val, true) = self.use_ecx(location, |this| { let val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?; - let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?; + let (_res, overflow) = this.ecx.overflowing_unary_op(op, &val)?; Ok((val, overflow)) })? { // `AssertKind` only has an `OverflowNeg` variant, so make sure that is @@ -390,7 +390,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let (Some(l), Some(r)) = (l, r) { // The remaining operators are handled through `overflowing_binary_op`. if self.use_ecx(location, |this| { - let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, &l, &r)?; + let (_res, overflow) = this.ecx.overflowing_binary_op(op, &l, &r)?; Ok(overflow) })? { let source_info = self.body().source_info(location); @@ -580,7 +580,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { self.super_operand(operand, location); } - fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) { trace!("visit_constant: {:?}", constant); self.super_constant(constant, location); self.eval_constant(constant, location); diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index d56d4ad4f1e7b..78845af016276 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,10 +1,8 @@ use super::Error; use super::graph; -use super::spans; use graph::{BasicCoverageBlock, BcbBranch, CoverageGraph, TraverseCoverageGraphWithLoops}; -use spans::CoverageSpan; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::WithNumNodes; @@ -93,14 +91,14 @@ impl CoverageCounters { } /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or - /// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s + /// indirectly associated with coverage spans, and accumulates additional `Expression`s /// representing intermediate values. pub fn make_bcb_counters( &mut self, basic_coverage_blocks: &CoverageGraph, - coverage_spans: &[CoverageSpan], + bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, ) -> Result<(), Error> { - MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans) + MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(bcb_has_coverage_spans) } fn make_counter(&mut self) -> BcbCounter { @@ -113,14 +111,10 @@ impl CoverageCounters { BcbCounter::Expression { id, lhs, op, rhs } } - pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter { - self.make_expression(counter_operand, Op::Add, Operand::Zero) - } - /// Counter IDs start from one and go up. fn next_counter(&mut self) -> CounterId { let next = self.next_counter_id; - self.next_counter_id = next.next_id(); + self.next_counter_id = self.next_counter_id + 1; next } @@ -128,7 +122,7 @@ impl CoverageCounters { /// (Counter IDs and Expression IDs are distinguished by the `Operand` enum.) fn next_expression(&mut self) -> ExpressionId { let next = self.next_expression_id; - self.next_expression_id = next.next_id(); + self.next_expression_id = self.next_expression_id + 1; next } @@ -208,7 +202,7 @@ impl CoverageCounters { } /// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be -/// injected with `CoverageSpan`s. `Expressions` have no runtime overhead, so if a viable expression +/// injected with coverage spans. `Expressions` have no runtime overhead, so if a viable expression /// (adding or subtracting two other counters or expressions) can compute the same result as an /// embedded counter, an `Expression` should be used. struct MakeBcbCounters<'a> { @@ -234,17 +228,14 @@ impl<'a> MakeBcbCounters<'a> { /// Returns any non-code-span expressions created to represent intermediate values (such as to /// add two counters so the result can be subtracted from another counter), or an Error with /// message for subsequent debugging. - fn make_bcb_counters(&mut self, coverage_spans: &[CoverageSpan]) -> Result<(), Error> { + fn make_bcb_counters( + &mut self, + bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, + ) -> Result<(), Error> { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); - let num_bcbs = self.basic_coverage_blocks.num_nodes(); - - let mut bcbs_with_coverage = BitSet::new_empty(num_bcbs); - for covspan in coverage_spans { - bcbs_with_coverage.insert(covspan.bcb); - } // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated - // `CoverageSpan`, add a counter. If the `BasicCoverageBlock` branches, add a counter or + // coverage span, add a counter. If the `BasicCoverageBlock` branches, add a counter or // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple // incoming edges). @@ -255,8 +246,8 @@ impl<'a> MakeBcbCounters<'a> { // the current BCB is in one or more nested loops or not. let mut traversal = TraverseCoverageGraphWithLoops::new(&self.basic_coverage_blocks); while let Some(bcb) = traversal.next(self.basic_coverage_blocks) { - if bcbs_with_coverage.contains(bcb) { - debug!("{:?} has at least one `CoverageSpan`. Get or make its counter", bcb); + if bcb_has_coverage_spans(bcb) { + debug!("{:?} has at least one coverage span. Get or make its counter", bcb); let branching_counter_operand = self.get_or_make_counter_operand(bcb)?; if self.bcb_needs_branch_counters(bcb) { @@ -264,7 +255,7 @@ impl<'a> MakeBcbCounters<'a> { } } else { debug!( - "{:?} does not have any `CoverageSpan`s. A counter will only be added if \ + "{:?} does not have any coverage spans. A counter will only be added if \ and when a covered BCB has an expression dependency.", bcb, ); diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index ff2254d6941e6..812633348e3bd 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -288,9 +288,9 @@ rustc_index::newtype_index! { /// not relevant to coverage analysis. `FalseUnwind`, for example, can be treated the same as /// a `Goto`, and merged with its successor into the same BCB. /// -/// Each BCB with at least one computed `CoverageSpan` will have no more than one `Counter`. +/// Each BCB with at least one computed coverage span will have no more than one `Counter`. /// In some cases, a BCB's execution count can be computed by `Expression`. Additional -/// disjoint `CoverageSpan`s in a BCB can also be counted by `Expression` (by adding `ZERO` +/// disjoint coverage spans in a BCB can also be counted by `Expression` (by adding `ZERO` /// to the BCB's primary counter or expression). /// /// The BCB CFG is critical to simplifying the coverage analysis by ensuring graph path-based diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index c75d33eeb315f..abf13519e9eea 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -9,13 +9,11 @@ mod tests; use self::counters::{BcbCounter, CoverageCounters}; use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; -use self::spans::{CoverageSpan, CoverageSpans}; +use self::spans::CoverageSpans; use crate::MirPass; -use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::sync::Lrc; -use rustc_index::IndexVec; use rustc_middle::hir; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; @@ -154,7 +152,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let body_span = self.body_span; //////////////////////////////////////////////////// - // Compute `CoverageSpan`s from the `CoverageGraph`. + // Compute coverage spans from the `CoverageGraph`. let coverage_spans = CoverageSpans::generate_coverage_spans( &self.mir_body, fn_sig_span, @@ -164,32 +162,33 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { //////////////////////////////////////////////////// // Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure - // every `CoverageSpan` has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` + // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` // and all `Expression` dependencies (operands) are also generated, for any other - // `BasicCoverageBlock`s not already associated with a `CoverageSpan`. + // `BasicCoverageBlock`s not already associated with a coverage span. // // Intermediate expressions (used to compute other `Expression` values), which have no // direct association with any `BasicCoverageBlock`, are accumulated inside `coverage_counters`. + let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb); let result = self .coverage_counters - .make_bcb_counters(&mut self.basic_coverage_blocks, &coverage_spans); + .make_bcb_counters(&mut self.basic_coverage_blocks, bcb_has_coverage_spans); if let Ok(()) = result { //////////////////////////////////////////////////// - // Remove the counter or edge counter from of each `CoverageSpan`s associated + // Remove the counter or edge counter from of each coverage cpan's associated // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR. // - // `Coverage` statements injected from `CoverageSpan`s will include the code regions + // `Coverage` statements injected from coverage spans will include the code regions // (source code start and end positions) to be counted by the associated counter. // - // These `CoverageSpan`-associated counters are removed from their associated + // These coverage-span-associated counters are removed from their associated // `BasicCoverageBlock`s so that the only remaining counters in the `CoverageGraph` // are indirect counters (to be injected next, without associated code regions). - self.inject_coverage_span_counters(coverage_spans); + self.inject_coverage_span_counters(&coverage_spans); //////////////////////////////////////////////////// // For any remaining `BasicCoverageBlock` counters (that were not associated with - // any `CoverageSpan`), inject `Coverage` statements (_without_ code region `Span`s) + // any coverage span), inject `Coverage` statements (_without_ code region spans) // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on // are in fact counted, even though they don't directly contribute to counting // their own independent code region's coverage. @@ -214,47 +213,40 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { } } - /// Inject a counter for each `CoverageSpan`. There can be multiple `CoverageSpan`s for a given - /// BCB, but only one actual counter needs to be incremented per BCB. `bb_counters` maps each - /// `bcb` to its `Counter`, when injected. Subsequent `CoverageSpan`s for a BCB that already has - /// a `Counter` will inject an `Expression` instead, and compute its value by adding `ZERO` to - /// the BCB `Counter` value. - fn inject_coverage_span_counters(&mut self, coverage_spans: Vec) { + /// Injects a single [`StatementKind::Coverage`] for each BCB that has one + /// or more coverage spans. + fn inject_coverage_span_counters(&mut self, coverage_spans: &CoverageSpans) { let tcx = self.tcx; let source_map = tcx.sess.source_map(); let body_span = self.body_span; let file_name = Symbol::intern(&self.source_file.name.prefer_remapped().to_string_lossy()); - let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes()); - for covspan in coverage_spans { - let bcb = covspan.bcb; - let span = covspan.span; - let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() { - self.coverage_counters.make_identity_counter(counter_operand) - } else if let Some(counter_kind) = self.coverage_counters.take_bcb_counter(bcb) { - bcb_counters[bcb] = Some(counter_kind.as_operand()); - counter_kind - } else { + for (bcb, spans) in coverage_spans.bcbs_with_coverage_spans() { + let counter_kind = self.coverage_counters.take_bcb_counter(bcb).unwrap_or_else(|| { bug!("Every BasicCoverageBlock should have a Counter or Expression"); - }; + }); - let code_region = make_code_region(source_map, file_name, span, body_span); + // Convert the coverage spans into a vector of code regions to be + // associated with this BCB's coverage statement. + let code_regions = spans + .iter() + .map(|&span| make_code_region(source_map, file_name, span, body_span)) + .collect::>(); inject_statement( self.mir_body, self.make_mir_coverage_kind(&counter_kind), self.bcb_leader_bb(bcb), - Some(code_region), + code_regions, ); } } - /// `inject_coverage_span_counters()` looped through the `CoverageSpan`s and injected the - /// counter from the `CoverageSpan`s `BasicCoverageBlock`, removing it from the BCB in the - /// process (via `take_counter()`). + /// At this point, any BCB with coverage counters has already had its counter injected + /// into MIR, and had its counter removed from `coverage_counters` (via `take_counter()`). /// /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not - /// associated with a `CoverageSpan`, should only exist if the counter is an `Expression` + /// associated with a coverage span, should only exist if the counter is an `Expression` /// dependency (one of the expression operands). Collect them, and inject the additional /// counters into the MIR, without a reportable coverage span. fn inject_indirect_counters(&mut self) { @@ -303,7 +295,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.mir_body, self.make_mir_coverage_kind(&counter_kind), inject_to_bb, - None, + Vec::new(), ); } BcbCounter::Expression { .. } => inject_intermediate_expression( @@ -368,20 +360,14 @@ fn inject_statement( mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb: BasicBlock, - some_code_region: Option, + code_regions: Vec, ) { - debug!( - " injecting statement {:?} for {:?} at code region: {:?}", - counter_kind, bb, some_code_region - ); + debug!(" injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}"); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: counter_kind, - code_region: some_code_region, - })), + kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })), }; data.statements.insert(0, statement); } @@ -395,7 +381,10 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: expression, code_region: None })), + kind: StatementKind::Coverage(Box::new(Coverage { + kind: expression, + code_regions: Vec::new(), + })), }; data.statements.push(statement); } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 56365c5d474a7..2c0164e765c76 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -93,8 +93,8 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { let body = mir_body(tcx, def_id); all_coverage_in_mir_body(body) - // Not all coverage statements have an attached code region. - .filter_map(|coverage| coverage.code_region.as_ref()) + // Coverage statements have a list of code regions (possibly empty). + .flat_map(|coverage| coverage.code_regions.as_slice()) .collect() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 5b24fa10beae8..dd87694f97cd0 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,6 +1,7 @@ use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB}; use rustc_data_structures::graph::WithNumNodes; +use rustc_index::IndexVec; use rustc_middle::mir::{ self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, @@ -10,6 +11,48 @@ use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol}; use std::cell::OnceCell; +pub(super) struct CoverageSpans { + /// Map from BCBs to their list of coverage spans. + bcb_to_spans: IndexVec>, +} + +impl CoverageSpans { + pub(super) fn generate_coverage_spans( + mir_body: &mir::Body<'_>, + fn_sig_span: Span, + body_span: Span, + basic_coverage_blocks: &CoverageGraph, + ) -> Self { + let coverage_spans = CoverageSpansGenerator::generate_coverage_spans( + mir_body, + fn_sig_span, + body_span, + basic_coverage_blocks, + ); + + // Group the coverage spans by BCB, with the BCBs in sorted order. + let mut bcb_to_spans = IndexVec::from_elem_n(Vec::new(), basic_coverage_blocks.num_nodes()); + for CoverageSpan { bcb, span, .. } in coverage_spans { + bcb_to_spans[bcb].push(span); + } + + Self { bcb_to_spans } + } + + pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool { + !self.bcb_to_spans[bcb].is_empty() + } + + pub(super) fn bcbs_with_coverage_spans( + &self, + ) -> impl Iterator { + self.bcb_to_spans.iter_enumerated().filter_map(|(bcb, spans)| { + // Only yield BCBs that have at least one coverage span. + (!spans.is_empty()).then_some((bcb, spans.as_slice())) + }) + } +} + #[derive(Debug, Copy, Clone)] pub(super) enum CoverageStatement { Statement(BasicBlock, Span, usize), @@ -35,7 +78,7 @@ impl CoverageStatement { /// or is subsumed by the `Span` associated with this `CoverageSpan`, and it's `BasicBlock` /// `dominates()` the `BasicBlock`s in this `CoverageSpan`. #[derive(Debug, Clone)] -pub(super) struct CoverageSpan { +struct CoverageSpan { pub span: Span, pub expn_span: Span, pub current_macro_or_none: OnceCell>, @@ -162,7 +205,7 @@ impl CoverageSpan { /// * Merge spans that represent continuous (both in source code and control flow), non-branching /// execution /// * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures) -pub struct CoverageSpans<'a, 'tcx> { +struct CoverageSpansGenerator<'a, 'tcx> { /// The MIR, used to look up `BasicBlockData`. mir_body: &'a mir::Body<'tcx>, @@ -218,7 +261,7 @@ pub struct CoverageSpans<'a, 'tcx> { refined_spans: Vec, } -impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { +impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> { /// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be /// counted. /// @@ -246,7 +289,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { body_span: Span, basic_coverage_blocks: &'a CoverageGraph, ) -> Vec { - let mut coverage_spans = CoverageSpans { + let mut coverage_spans = Self { mir_body, fn_sig_span, body_span, @@ -734,7 +777,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { /// If the MIR `Statement` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option { +fn filtered_statement_span(statement: &Statement<'_>) -> Option { match statement.kind { // These statements have spans that are often outside the scope of the executed source code // for their parent `BasicBlock`. @@ -763,7 +806,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option // and `_1` is the `Place` for `somenum`. // // If and when the Issue is resolved, remove this special case match pattern: - StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None, + StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None, // Retain spans from all other statements StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` @@ -781,7 +824,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option /// If the MIR `Terminator` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { +fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { match terminator.kind { // These terminators have spans that don't positively contribute to computing a reasonable // span of actually executed source code. (For example, SwitchInt terminators extracted from @@ -828,7 +871,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option Span { +fn function_source_span(span: Span, body_span: Span) -> Span { let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); if body_span.contains(original_span) { original_span } else { body_span } } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 4a066ed3abdea..7476d3ce9272a 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -25,8 +25,7 @@ //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`. use super::counters; -use super::graph; -use super::spans; +use super::graph::{self, BasicCoverageBlock}; use coverage_test_macros::let_bcb; @@ -644,39 +643,18 @@ fn test_traverse_coverage_with_loops() { ); } -fn synthesize_body_span_from_terminators(mir_body: &Body<'_>) -> Span { - let mut some_span: Option = None; - for (_, data) in mir_body.basic_blocks.iter_enumerated() { - let term_span = data.terminator().source_info.span; - if let Some(span) = some_span.as_mut() { - *span = span.to(term_span); - } else { - some_span = Some(term_span) - } - } - some_span.expect("body must have at least one BasicBlock") -} - #[test] fn test_make_bcb_counters() { rustc_span::create_default_session_globals_then(|| { let mir_body = goto_switchint(); - let body_span = synthesize_body_span_from_terminators(&mir_body); let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); - let mut coverage_spans = Vec::new(); - for (bcb, data) in basic_coverage_blocks.iter_enumerated() { - if let Some(span) = spans::filtered_terminator_span(data.terminator(&mir_body)) { - coverage_spans.push(spans::CoverageSpan::for_terminator( - spans::function_source_span(span, body_span), - span, - bcb, - data.last_bb(), - )); - } - } + // Historically this test would use `spans` internals to set up fake + // coverage spans for BCBs 1 and 2. Now we skip that step and just tell + // BCB counter construction that those BCBs have spans. + let bcb_has_coverage_spans = |bcb: BasicCoverageBlock| (1..=2).contains(&bcb.as_usize()); let mut coverage_counters = counters::CoverageCounters::new(&basic_coverage_blocks); coverage_counters - .make_bcb_counters(&mut basic_coverage_blocks, &coverage_spans) + .make_bcb_counters(&mut basic_coverage_blocks, bcb_has_coverage_spans) .expect("should be Ok"); assert_eq!(coverage_counters.intermediate_expressions.len(), 0); diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index cf827c988942b..7b14fef6153c5 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -206,7 +206,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { && let operand_ty = operand.ty(self.local_decls, self.tcx) && let Some(operand_ty) = operand_ty.builtin_deref(true) && let ty::Array(_, len) = operand_ty.ty.kind() - && let Some(len) = ConstantKind::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env) + && let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env) { state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map()); } @@ -224,7 +224,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { Rvalue::Len(place) => { let place_ty = place.ty(self.local_decls, self.tcx); if let ty::Array(_, len) = place_ty.ty.kind() { - ConstantKind::Ty(*len) + Const::Ty(*len) .try_eval_scalar(self.tcx, self.param_env) .map_or(FlatSet::Top, FlatSet::Elem) } else if let [ProjectionElem::Deref] = place.projection[..] { @@ -234,21 +234,27 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } } Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { + let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + return ValueOrPlace::Value(FlatSet::Top); + }; match self.eval_operand(operand, state) { FlatSet::Elem(op) => self .ecx - .int_to_int_or_float(&op, *ty) - .map_or(FlatSet::Top, |result| self.wrap_immediate(result)), + .int_to_int_or_float(&op, layout) + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)), FlatSet::Bottom => FlatSet::Bottom, FlatSet::Top => FlatSet::Top, } } Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { + let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + return ValueOrPlace::Value(FlatSet::Top); + }; match self.eval_operand(operand, state) { FlatSet::Elem(op) => self .ecx - .float_to_float_or_int(&op, *ty) - .map_or(FlatSet::Top, |result| self.wrap_immediate(result)), + .float_to_float_or_int(&op, layout) + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)), FlatSet::Bottom => FlatSet::Bottom, FlatSet::Top => FlatSet::Top, } @@ -268,7 +274,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { FlatSet::Elem(value) => self .ecx - .unary_op(*op, &value) + .wrapping_unary_op(*op, &value) .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)), FlatSet::Bottom => FlatSet::Bottom, FlatSet::Top => FlatSet::Top, @@ -295,11 +301,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { fn handle_constant( &self, - constant: &Constant<'tcx>, + constant: &ConstOperand<'tcx>, _state: &mut State, ) -> Self::Value { constant - .literal + .const_ .try_eval_scalar(self.tcx, self.param_env) .map_or(FlatSet::Top, FlatSet::Elem) } @@ -360,7 +366,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Operand::Constant(box constant) => { - if let Ok(constant) = self.ecx.eval_mir_constant(&constant.literal, None, None) { + if let Ok(constant) = self.ecx.eval_mir_constant(&constant.const_, None, None) { self.assign_constant(state, place, constant, &[]); } } @@ -439,7 +445,9 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // Both sides are known, do the actual computation. (FlatSet::Elem(left), FlatSet::Elem(right)) => { match self.ecx.overflowing_binary_op(op, &left, &right) { - Ok((val, overflow, _)) => (FlatSet::Elem(val), FlatSet::Elem(overflow)), + Ok((val, overflow)) => { + (FlatSet::Elem(val.to_scalar()), FlatSet::Elem(overflow)) + } _ => (FlatSet::Top, FlatSet::Top), } } @@ -518,10 +526,10 @@ pub(crate) struct Patch<'tcx> { /// For a given MIR location, this stores the values of the operands used by that location. In /// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are /// properly captured. (This may become UB soon, but it is currently emitted even by safe code.) - pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), ConstantKind<'tcx>>, + pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>, /// Stores the assigned values for assignments where the Rvalue is constant. - pub(crate) assignments: FxHashMap>, + pub(crate) assignments: FxHashMap>, } impl<'tcx> Patch<'tcx> { @@ -529,8 +537,8 @@ impl<'tcx> Patch<'tcx> { Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() } } - fn make_operand(&self, literal: ConstantKind<'tcx>) -> Operand<'tcx> { - Operand::Constant(Box::new(Constant { span: DUMMY_SP, user_ty: None, literal })) + fn make_operand(&self, const_: Const<'tcx>) -> Operand<'tcx> { + Operand::Constant(Box::new(ConstOperand { span: DUMMY_SP, user_ty: None, const_ })) } } @@ -549,12 +557,12 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> { place: Place<'tcx>, state: &State>, map: &Map, - ) -> Option> { + ) -> Option> { let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else { return None; }; let ty = place.ty(self.local_decls, self.patch.tcx).ty; - Some(ConstantKind::Val(ConstValue::Scalar(value.into()), ty)) + Some(Const::Val(ConstValue::Scalar(value.into()), ty)) } } @@ -783,8 +791,8 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _bin_op: BinOp, _left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, _right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, - ) -> interpret::InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { - throw_unsup!(Unsupported("".into())) + ) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> { + crate::const_prop::throw_machine_stop_str!("can't do pointer arithmetic"); } fn expose_ptr( diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index ef14105041b4f..3d74ef7e3278e 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -13,10 +13,10 @@ //! use crate::util::is_within_packed; -use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::debuginfo::debuginfo_locals; use rustc_mir_dataflow::impls::{ borrowed_locals, LivenessTransferFunction, MaybeTransitiveLiveLocals, }; @@ -26,8 +26,15 @@ use rustc_mir_dataflow::Analysis; /// /// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It /// can be generated via the [`borrowed_locals`] function. -pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet) { - let mut live = MaybeTransitiveLiveLocals::new(borrowed) +pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let borrowed_locals = borrowed_locals(body); + + // If the user requests complete debuginfo, mark the locals that appear in it as live, so + // we don't remove assignements to them. + let mut always_live = debuginfo_locals(body); + always_live.union(&borrowed_locals); + + let mut live = MaybeTransitiveLiveLocals::new(&always_live) .into_engine(tcx, body) .iterate_to_fixpoint() .into_results_cursor(body); @@ -48,7 +55,9 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS for (index, arg) in args.iter().enumerate().rev() { if let Operand::Copy(place) = *arg && !place.is_indirect() - && !borrowed.contains(place.local) + // Do not skip the transformation if the local is in debuginfo, as we do + // not really lose any information for this purpose. + && !borrowed_locals.contains(place.local) && !state.contains(place.local) // If `place` is a projection of a disaligned field in a packed ADT, // the move may be codegened as a pointer to that field. @@ -75,7 +84,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS StatementKind::Assign(box (place, _)) | StatementKind::SetDiscriminant { place: box place, .. } | StatementKind::Deinit(box place) => { - if !place.is_indirect() && !borrowed.contains(place.local) { + if !place.is_indirect() && !always_live.contains(place.local) { live.seek_before_primary_effect(loc); if !live.get().contains(place.local) { patch.push(loc); @@ -126,7 +135,6 @@ impl<'tcx> MirPass<'tcx> for DeadStoreElimination { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let borrowed = borrowed_locals(body); - eliminate(tcx, body, &borrowed); + eliminate(tcx, body); } } diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index 909116a77f54f..666293cbc3071 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -150,7 +150,7 @@ fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'_>) { fn operand_hash(hasher: &mut H, operand: &Operand<'_>) { match operand { - Operand::Constant(box Constant { user_ty: _, literal, span: _ }) => literal.hash(hasher), + Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher), x => x.hash(hasher), }; } @@ -179,9 +179,9 @@ fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { let res = match (lhs, rhs) { ( - Operand::Constant(box Constant { user_ty: _, literal, span: _ }), - Operand::Constant(box Constant { user_ty: _, literal: literal2, span: _ }), - ) => literal == literal2, + Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }), + Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }), + ) => const_ == const2, (x, y) => x == y, }; debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 95898b5b73cdb..42be745701846 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() { if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref { let ty = p_ref.ty(self.local_decls, self.tcx).ty; - let temp = self.patcher.new_internal_with_info( + let temp = self.patcher.new_local_with_info( ty, self.local_decls[p_ref.local].source_info.span, LocalInfo::DerefTemp, diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e51f771e00dbe..1c917a85c038e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -69,7 +69,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { let (unique_ty, nonnull_ty, ptr_ty) = build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); - let ptr_local = self.patch.new_internal(ptr_ty, source_info.span); + let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); self.patch.add_assign( location, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 78d7ffb3698a0..d18fdaaf22ff4 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -170,6 +170,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { self.ctxt.param_env() } + #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false), @@ -270,7 +271,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tcx = self.tcx; let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); - self.drop_flags[index].get_or_insert_with(|| patch.new_internal(tcx.types.bool, span)); + self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span)); } fn drop_flag(&mut self, index: MovePathIndex) -> Option> { @@ -402,10 +403,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { - Rvalue::Use(Operand::Constant(Box::new(Constant { + Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span, user_ty: None, - literal: ConstantKind::from_bool(self.tcx, val), + const_: Const::from_bool(self.tcx, val), }))) } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 35373bcaa41d5..5879a803946d6 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -4,7 +4,9 @@ use rustc_errors::{ }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; +use rustc_middle::ty::TyCtxt; use rustc_session::lint::{self, Lint}; +use rustc_span::def_id::DefId; use rustc_span::Span; #[derive(LintDiagnostic)] @@ -237,20 +239,38 @@ pub(crate) struct FnItemRef { pub ident: String, } -#[derive(LintDiagnostic)] -#[diag(mir_transform_must_not_suspend)] -pub(crate) struct MustNotSupend<'a> { - #[label] +pub(crate) struct MustNotSupend<'tcx, 'a> { + pub tcx: TyCtxt<'tcx>, pub yield_sp: Span, - #[subdiagnostic] pub reason: Option, - #[help] pub src_sp: Span, pub pre: &'a str, - pub def_path: String, + pub def_id: DefId, pub post: &'a str, } +// Needed for def_path_str +impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.span_label(self.yield_sp, crate::fluent_generated::_subdiag::label); + if let Some(reason) = self.reason { + diag.subdiagnostic(reason); + } + diag.span_help(self.src_sp, crate::fluent_generated::_subdiag::help); + diag.set_arg("pre", self.pre); + diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); + diag.set_arg("post", self.post); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + crate::fluent_generated::mir_transform_must_not_suspend + } +} + #[derive(Subdiagnostic)] #[note(mir_transform_note)] pub(crate) struct MustNotSuspendReason { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index eae83448c46f3..c16f07a453c3d 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -321,7 +321,7 @@ impl<'tcx> TransformVisitor<'tcx> { // Create a statement which reads the discriminant into a temporary fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) { - let temp_decl = LocalDecl::new(self.discr_ty, body.span).internal(); + let temp_decl = LocalDecl::new(self.discr_ty, body.span); let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); @@ -853,60 +853,7 @@ impl StorageConflictVisitor<'_, '_, '_> { } } -/// Validates the typeck view of the generator against the actual set of types saved between -/// yield points. -fn sanitize_witness<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - witness: Ty<'tcx>, - upvars: &'tcx ty::List>, - layout: &GeneratorLayout<'tcx>, -) { - let did = body.source.def_id(); - let param_env = tcx.param_env(did); - - let allowed_upvars = tcx.normalize_erasing_regions(param_env, upvars); - let allowed = match witness.kind() { - &ty::GeneratorWitness(interior_tys) => { - tcx.normalize_erasing_late_bound_regions(param_env, interior_tys) - } - _ => { - tcx.sess.delay_span_bug( - body.span, - format!("unexpected generator witness type {:?}", witness.kind()), - ); - return; - } - }; - - let mut mismatches = Vec::new(); - for fty in &layout.field_tys { - if fty.ignore_for_traits { - continue; - } - let decl_ty = tcx.normalize_erasing_regions(param_env, fty.ty); - - // Sanity check that typeck knows about the type of locals which are - // live across a suspension point - if !allowed.contains(&decl_ty) && !allowed_upvars.contains(&decl_ty) { - mismatches.push(decl_ty); - } - } - - if !mismatches.is_empty() { - span_bug!( - body.span, - "Broken MIR: generator contains type {:?} in MIR, \ - but typeck only knows about {} and {:?}", - mismatches, - allowed, - allowed_upvars - ); - } -} - fn compute_layout<'tcx>( - tcx: TyCtxt<'tcx>, liveness: LivenessInfo, body: &Body<'tcx>, ) -> ( @@ -932,27 +879,20 @@ fn compute_layout<'tcx>( let decl = &body.local_decls[local]; debug!(?decl); - let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir { - // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared - // the information. This is alright, since `ignore_for_traits` is only relevant when - // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer - // default. - match decl.local_info { - // Do not include raw pointers created from accessing `static` items, as those could - // well be re-created by another access to the same static. - ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => { - !is_thread_local - } - // Fake borrows are only read by fake reads, so do not have any reality in - // post-analysis MIR. - ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true, - _ => false, + // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared + // the information. This is alright, since `ignore_for_traits` is only relevant when + // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer + // default. + let ignore_for_traits = match decl.local_info { + // Do not include raw pointers created from accessing `static` items, as those could + // well be re-created by another access to the same static. + ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => { + !is_thread_local } - } else { - // FIXME(#105084) HIR-based drop tracking does not account for all the temporaries that - // MIR building may introduce. This leads to wrongly ignored types, but this is - // necessary for internal consistency and to avoid ICEs. - decl.internal + // Fake borrows are only read by fake reads, so do not have any reality in + // post-analysis MIR. + ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true, + _ => false, }; let decl = GeneratorSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits }; @@ -1189,10 +1129,10 @@ fn insert_panic_block<'tcx>( ) -> BasicBlock { let assert_block = BasicBlock::new(body.basic_blocks.len()); let term = TerminatorKind::Assert { - cond: Operand::Constant(Box::new(Constant { + cond: Operand::Constant(Box::new(ConstOperand { span: body.span, user_ty: None, - literal: ConstantKind::from_bool(tcx, false), + const_: Const::from_bool(tcx, false), })), expected: true, msg: Box::new(message), @@ -1445,8 +1385,6 @@ pub(crate) fn mir_generator_witnesses<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> Option> { - assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir); - let (body, _) = tcx.mir_promoted(def_id); let body = body.borrow(); let body = &*body; @@ -1469,7 +1407,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>( // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices // `storage_liveness` tells us which locals have live storage at suspension points - let (_, generator_layout, _) = compute_layout(tcx, liveness_info, body); + let (_, generator_layout, _) = compute_layout(liveness_info, body); check_suspend_tys(tcx, &generator_layout, &body); @@ -1489,15 +1427,10 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let gen_ty = body.local_decls.raw[1].ty; // Get the discriminant type and args which typeck computed - let (discr_ty, upvars, interior, movable) = match *gen_ty.kind() { + let (discr_ty, movable) = match *gen_ty.kind() { ty::Generator(_, args, movability) => { let args = args.as_generator(); - ( - args.discr_ty(tcx), - args.upvar_tys(), - args.witness(), - movability == hir::Movability::Movable, - ) + (args.discr_ty(tcx), movability == hir::Movability::Movable) } _ => { tcx.sess.delay_span_bug(body.span, format!("unexpected generator type {gen_ty}")); @@ -1574,13 +1507,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices // `storage_liveness` tells us which locals have live storage at suspension points - let (remap, layout, storage_liveness) = compute_layout(tcx, liveness_info, body); - - if tcx.sess.opts.unstable_opts.validate_mir - && !tcx.sess.opts.unstable_opts.drop_tracking_mir - { - sanitize_witness(tcx, body, interior, upvars, &layout); - } + let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id())); @@ -1954,11 +1881,12 @@ fn check_must_not_suspend_def( hir_id, data.source_span, errors::MustNotSupend { + tcx, yield_sp: data.yield_span, reason, src_sp: data.source_span, pre: data.descr_pre, - def_path: tcx.def_path_str(def_id), + def_id, post: data.descr_post, }, ); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs new file mode 100644 index 0000000000000..56bdc5a171acc --- /dev/null +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -0,0 +1,539 @@ +//! Global value numbering. +//! +//! MIR may contain repeated and/or redundant computations. The objective of this pass is to detect +//! such redundancies and re-use the already-computed result when possible. +//! +//! In a first pass, we compute a symbolic representation of values that are assigned to SSA +//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of +//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. +//! +//! From those assignments, we construct a mapping `VnIndex -> Vec<(Local, Location)>` of available +//! values, the locals in which they are stored, and a the assignment location. +//! +//! In a second pass, we traverse all (non SSA) assignments `x = rvalue` and operands. For each +//! one, we compute the `VnIndex` of the rvalue. If this `VnIndex` is associated to a constant, we +//! replace the rvalue/operand by that constant. Otherwise, if there is an SSA local `y` +//! associated to this `VnIndex`, and if its definition location strictly dominates the assignment +//! to `x`, we replace the assignment by `x = y`. +//! +//! By opportunity, this pass simplifies some `Rvalue`s based on the accumulated knowledge. +//! +//! # Operational semantic +//! +//! Operationally, this pass attempts to prove bitwise equality between locals. Given this MIR: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _b = some other value // also has VnIndex i +//! ``` +//! +//! We consider it to be replacable by: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _c = some other value // also has VnIndex i +//! assume(_a bitwise equal to _c) // follows from having the same VnIndex +//! _b = _a // follows from the `assume` +//! ``` +//! +//! Which is simplifiable to: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _b = _a +//! ``` +//! +//! # Handling of references +//! +//! We handle references by assigning a different "provenance" index to each Ref/AddressOf rvalue. +//! This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we +//! consider all the derefs of an immutable reference to a freeze type to give the same value: +//! ```ignore (MIR) +//! _a = *_b // _b is &Freeze +//! _c = *_b // replaced by _c = _a +//! ``` + +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::graph::dominators::Dominators; +use rustc_index::bit_set::BitSet; +use rustc_index::IndexVec; +use rustc_macros::newtype_index; +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; + +use crate::ssa::SsaLocals; +use crate::MirPass; + +pub struct GVN; + +impl<'tcx> MirPass<'tcx> for GVN { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + + #[instrument(level = "trace", skip(self, tcx, body))] + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!(def_id = ?body.source.def_id()); + propagate_ssa(tcx, body); + } +} + +fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(body); + // Clone dominators as we need them while mutating the body. + let dominators = body.basic_blocks.dominators().clone(); + + let mut state = VnState::new(tcx, param_env, &ssa, &dominators, &body.local_decls); + for arg in body.args_iter() { + if ssa.is_ssa(arg) { + let value = state.new_opaque().unwrap(); + state.assign(arg, value); + } + } + + ssa.for_each_assignment_mut(&mut body.basic_blocks, |local, rvalue, location| { + let value = state.simplify_rvalue(rvalue, location).or_else(|| state.new_opaque()).unwrap(); + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as + // reusable if we have an exact type match. + if state.local_decls[local].ty == rvalue.ty(state.local_decls, tcx) { + state.assign(local, value); + } + }); + + // Stop creating opaques during replacement as it is useless. + state.next_opaque = None; + + let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); + for bb in reverse_postorder { + let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; + state.visit_basic_block_data(bb, data); + } + let any_replacement = state.any_replacement; + + // For each local that is reused (`y` above), we remove its storage statements do avoid any + // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage + // statements. + StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + + if any_replacement { + crate::simplify::remove_unused_definitions(body); + } +} + +newtype_index! { + struct VnIndex {} +} + +#[derive(Debug, PartialEq, Eq, Hash)] +enum Value<'tcx> { + // Root values. + /// Used to represent values we know nothing about. + /// The `usize` is a counter incremented by `new_opaque`. + Opaque(usize), + /// Evaluated or unevaluated constant value. + Constant(Const<'tcx>), + /// An aggregate value, either tuple/closure/struct/enum. + /// This does not contain unions, as we cannot reason with the value. + Aggregate(Ty<'tcx>, VariantIdx, Vec), + /// This corresponds to a `[value; count]` expression. + Repeat(VnIndex, ty::Const<'tcx>), + /// The address of a place. + Address { + place: Place<'tcx>, + /// Give each borrow and pointer a different provenance, so we don't merge them. + provenance: usize, + }, + + // Extractions. + /// This is the *value* obtained by projecting another value. + Projection(VnIndex, ProjectionElem>), + /// Discriminant of the given value. + Discriminant(VnIndex), + /// Length of an array or slice. + Len(VnIndex), + + // Operations. + NullaryOp(NullOp<'tcx>, Ty<'tcx>), + UnaryOp(UnOp, VnIndex), + BinaryOp(BinOp, VnIndex, VnIndex), + CheckedBinaryOp(BinOp, VnIndex, VnIndex), + Cast { + kind: CastKind, + value: VnIndex, + from: Ty<'tcx>, + to: Ty<'tcx>, + }, +} + +struct VnState<'body, 'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + local_decls: &'body LocalDecls<'tcx>, + /// Value stored in each local. + locals: IndexVec>, + /// First local to be assigned that value. + rev_locals: FxHashMap>, + values: FxIndexSet>, + /// Counter to generate different values. + /// This is an option to stop creating opaques during replacement. + next_opaque: Option, + ssa: &'body SsaLocals, + dominators: &'body Dominators, + reused_locals: BitSet, + any_replacement: bool, +} + +impl<'body, 'tcx> VnState<'body, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ssa: &'body SsaLocals, + dominators: &'body Dominators, + local_decls: &'body LocalDecls<'tcx>, + ) -> Self { + VnState { + tcx, + param_env, + local_decls, + locals: IndexVec::from_elem(None, local_decls), + rev_locals: FxHashMap::default(), + values: FxIndexSet::default(), + next_opaque: Some(0), + ssa, + dominators, + reused_locals: BitSet::new_empty(local_decls.len()), + any_replacement: false, + } + } + + #[instrument(level = "trace", skip(self), ret)] + fn insert(&mut self, value: Value<'tcx>) -> VnIndex { + let (index, _) = self.values.insert_full(value); + VnIndex::from_usize(index) + } + + /// Create a new `Value` for which we have no information at all, except that it is distinct + /// from all the others. + #[instrument(level = "trace", skip(self), ret)] + fn new_opaque(&mut self) -> Option { + let next_opaque = self.next_opaque.as_mut()?; + let value = Value::Opaque(*next_opaque); + *next_opaque += 1; + Some(self.insert(value)) + } + + /// Create a new `Value::Address` distinct from all the others. + #[instrument(level = "trace", skip(self), ret)] + fn new_pointer(&mut self, place: Place<'tcx>) -> Option { + let next_opaque = self.next_opaque.as_mut()?; + let value = Value::Address { place, provenance: *next_opaque }; + *next_opaque += 1; + Some(self.insert(value)) + } + + fn get(&self, index: VnIndex) -> &Value<'tcx> { + self.values.get_index(index.as_usize()).unwrap() + } + + /// Record that `local` is assigned `value`. `local` must be SSA. + #[instrument(level = "trace", skip(self))] + fn assign(&mut self, local: Local, value: VnIndex) { + self.locals[local] = Some(value); + + // Only register the value if its type is `Sized`, as we will emit copies of it. + let is_sized = !self.tcx.features().unsized_locals + || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); + if is_sized { + self.rev_locals.entry(value).or_default().push(local); + } + } + + /// Represent the *value* which would be read from `place`, and point `place` to a preexisting + /// place with the same value (if that already exists). + #[instrument(level = "trace", skip(self), ret)] + fn simplify_place_value( + &mut self, + place: &mut Place<'tcx>, + location: Location, + ) -> Option { + // Invariant: `place` and `place_ref` point to the same value, even if they point to + // different memory locations. + let mut place_ref = place.as_ref(); + + // Invariant: `value` holds the value up-to the `index`th projection excluded. + let mut value = self.locals[place.local]?; + for (index, proj) in place.projection.iter().enumerate() { + if let Some(local) = self.try_as_local(value, location) { + // Both `local` and `Place { local: place.local, projection: projection[..index] }` + // hold the same value. Therefore, following place holds the value in the original + // `place`. + place_ref = PlaceRef { local, projection: &place.projection[index..] }; + } + + let proj = match proj { + ProjectionElem::Deref => { + let ty = Place::ty_from( + place.local, + &place.projection[..index], + self.local_decls, + self.tcx, + ) + .ty; + if let Some(Mutability::Not) = ty.ref_mutability() + && let Some(pointee_ty) = ty.builtin_deref(true) + && pointee_ty.ty.is_freeze(self.tcx, self.param_env) + { + // An immutable borrow `_x` always points to the same value for the + // lifetime of the borrow, so we can merge all instances of `*_x`. + ProjectionElem::Deref + } else { + return None; + } + } + ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty), + ProjectionElem::Index(idx) => { + let idx = self.locals[idx]?; + ProjectionElem::Index(idx) + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Subslice { from, to, from_end } => { + ProjectionElem::Subslice { from, to, from_end } + } + ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index), + ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty), + ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty), + }; + value = self.insert(Value::Projection(value, proj)); + } + + if let Some(local) = self.try_as_local(value, location) + && local != place.local // in case we had no projection to begin with. + { + *place = local.into(); + self.reused_locals.insert(local); + self.any_replacement = true; + } else if place_ref.local != place.local + || place_ref.projection.len() < place.projection.len() + { + // By the invariant on `place_ref`. + *place = place_ref.project_deeper(&[], self.tcx); + self.reused_locals.insert(place_ref.local); + self.any_replacement = true; + } + + Some(value) + } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_operand( + &mut self, + operand: &mut Operand<'tcx>, + location: Location, + ) -> Option { + match *operand { + Operand::Constant(ref constant) => Some(self.insert(Value::Constant(constant.const_))), + Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { + let value = self.simplify_place_value(place, location)?; + if let Some(const_) = self.try_as_constant(value) { + *operand = Operand::Constant(Box::new(const_)); + self.any_replacement = true; + } + Some(value) + } + } + } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_rvalue( + &mut self, + rvalue: &mut Rvalue<'tcx>, + location: Location, + ) -> Option { + let value = match *rvalue { + // Forward values. + Rvalue::Use(ref mut operand) => return self.simplify_operand(operand, location), + Rvalue::CopyForDeref(place) => { + let mut operand = Operand::Copy(place); + let val = self.simplify_operand(&mut operand, location); + *rvalue = Rvalue::Use(operand); + return val; + } + + // Roots. + Rvalue::Repeat(ref mut op, amount) => { + let op = self.simplify_operand(op, location)?; + Value::Repeat(op, amount) + } + Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty), + Rvalue::Aggregate(box ref kind, ref mut fields) => { + let variant_index = match *kind { + AggregateKind::Array(..) + | AggregateKind::Tuple + | AggregateKind::Closure(..) + | AggregateKind::Generator(..) => FIRST_VARIANT, + AggregateKind::Adt(_, variant_index, _, _, None) => variant_index, + // Do not track unions. + AggregateKind::Adt(_, _, _, _, Some(_)) => return None, + }; + let fields: Option> = fields + .iter_mut() + .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque())) + .collect(); + let ty = rvalue.ty(self.local_decls, self.tcx); + Value::Aggregate(ty, variant_index, fields?) + } + Rvalue::Ref(.., place) | Rvalue::AddressOf(_, place) => return self.new_pointer(place), + + // Operations. + Rvalue::Len(ref mut place) => { + let place = self.simplify_place_value(place, location)?; + Value::Len(place) + } + Rvalue::Cast(kind, ref mut value, to) => { + let from = value.ty(self.local_decls, self.tcx); + let value = self.simplify_operand(value, location)?; + Value::Cast { kind, value, from, to } + } + Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let lhs = self.simplify_operand(lhs, location); + let rhs = self.simplify_operand(rhs, location); + Value::BinaryOp(op, lhs?, rhs?) + } + Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let lhs = self.simplify_operand(lhs, location); + let rhs = self.simplify_operand(rhs, location); + Value::CheckedBinaryOp(op, lhs?, rhs?) + } + Rvalue::UnaryOp(op, ref mut arg) => { + let arg = self.simplify_operand(arg, location)?; + Value::UnaryOp(op, arg) + } + Rvalue::Discriminant(ref mut place) => { + let place = self.simplify_place_value(place, location)?; + Value::Discriminant(place) + } + + // Unsupported values. + Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None, + }; + debug!(?value); + Some(self.insert(value)) + } +} + +impl<'tcx> VnState<'_, 'tcx> { + /// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR. + fn try_as_constant(&mut self, index: VnIndex) -> Option> { + if let Value::Constant(const_) = *self.get(index) { + // Some constants may contain pointers. We need to preserve the provenance of these + // pointers, but not all constants guarantee this: + // - valtrees purposefully do not; + // - ConstValue::Slice does not either. + match const_ { + Const::Ty(c) => match c.kind() { + ty::ConstKind::Value(valtree) => match valtree { + // This is just an integer, keep it. + ty::ValTree::Leaf(_) => {} + ty::ValTree::Branch(_) => return None, + }, + ty::ConstKind::Param(..) + | ty::ConstKind::Unevaluated(..) + | ty::ConstKind::Expr(..) => {} + // Should not appear in runtime MIR. + ty::ConstKind::Infer(..) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(..) + | ty::ConstKind::Error(..) => bug!(), + }, + Const::Unevaluated(..) => {} + // If the same slice appears twice in the MIR, we cannot guarantee that we will + // give the same `AllocId` to the data. + Const::Val(ConstValue::Slice { .. }, _) => return None, + Const::Val( + ConstValue::ZeroSized | ConstValue::Scalar(_) | ConstValue::Indirect { .. }, + _, + ) => {} + } + Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_ }) + } else { + None + } + } + + /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, + /// return it. + fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option { + let other = self.rev_locals.get(&index)?; + other + .iter() + .copied() + .find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc)) + } +} + +impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + self.simplify_operand(operand, location); + } + + fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { + self.super_statement(stmt, location); + if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind + // Do not try to simplify a constant, it's already in canonical shape. + && !matches!(rvalue, Rvalue::Use(Operand::Constant(_))) + && let Some(value) = self.simplify_rvalue(rvalue, location) + { + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + self.any_replacement = true; + } else if let Some(local) = self.try_as_local(value, location) + && *rvalue != Rvalue::Use(Operand::Move(local.into())) + { + *rvalue = Rvalue::Use(Operand::Copy(local.into())); + self.reused_locals.insert(local); + self.any_replacement = true; + } + } + } +} + +struct StorageRemover<'tcx> { + tcx: TyCtxt<'tcx>, + reused_locals: BitSet, +} + +impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { + if let Operand::Move(place) = *operand + && let Some(local) = place.as_local() + && self.reused_locals.contains(local) + { + *operand = Operand::Copy(place); + } + } + + fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) { + match stmt.kind { + // When removing storage statements, we need to remove both (#107511). + StatementKind::StorageLive(l) | StatementKind::StorageDead(l) + if self.reused_locals.contains(l) => + { + stmt.make_nop() + } + _ => self.super_statement(stmt, loc), + } + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 4dc7c3b644441..32dfb7439053e 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -193,7 +193,7 @@ impl<'tcx> Inliner<'tcx> { return Err("optimization fuel exhausted"); } - let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions( + let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, self.param_env, ty::EarlyBinder::bind(callee_body.clone()), @@ -218,7 +218,13 @@ impl<'tcx> Inliner<'tcx> { // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. let output_type = callee_body.return_ty(); - if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) { + if !util::relate_types( + self.tcx, + self.param_env, + ty::Variance::Covariant, + output_type, + destination_ty, + ) { trace!(?output_type, ?destination_ty); return Err("failed to normalize return type"); } @@ -248,7 +254,13 @@ impl<'tcx> Inliner<'tcx> { self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; - if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) { + if !util::relate_types( + self.tcx, + self.param_env, + ty::Variance::Covariant, + input_type, + arg_ty, + ) { trace!(?arg_ty, ?input_type); return Err("failed to normalize tuple argument type"); } @@ -257,7 +269,13 @@ impl<'tcx> Inliner<'tcx> { for (arg, input) in args.iter().zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; let arg_ty = arg.ty(&caller_body.local_decls, self.tcx); - if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) { + if !util::relate_types( + self.tcx, + self.param_env, + ty::Variance::Covariant, + input_type, + arg_ty, + ) { trace!(?arg_ty, ?input_type); return Err("failed to normalize argument type"); } @@ -481,9 +499,10 @@ impl<'tcx> Inliner<'tcx> { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = callsite - .callee - .subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty)); + let ty = callsite.callee.instantiate_mir( + self.tcx, + ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); } @@ -597,9 +616,7 @@ impl<'tcx> Inliner<'tcx> { // If there are any locals without storage markers, give them storage only for the // duration of the call. for local in callee_body.vars_and_temps_iter() { - if !callee_body.local_decls[local].internal - && integrator.always_live_locals.contains(local) - { + if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, @@ -622,9 +639,7 @@ impl<'tcx> Inliner<'tcx> { n += 1; } for local in callee_body.vars_and_temps_iter().rev() { - if !callee_body.local_decls[local].internal - && integrator.always_live_locals.contains(local) - { + if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); caller_body[block].statements.push(Statement { source_info: callsite.source_info, @@ -650,13 +665,13 @@ impl<'tcx> Inliner<'tcx> { // Copy only unevaluated constants from the callee_body into the caller_body. // Although we are only pushing `ConstKind::Unevaluated` consts to // `required_consts`, here we may not only have `ConstKind::Unevaluated` - // because we are calling `subst_and_normalize_erasing_regions`. + // because we are calling `instantiate_and_normalize_erasing_regions`. caller_body.required_consts.extend( - callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal { - ConstantKind::Ty(_) => { + callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ { + Const::Ty(_) => { bug!("should never encounter ty::UnevaluatedConst in `required_consts`") } - ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true, + Const::Val(..) | Const::Unevaluated(..) => true, }), ); } @@ -811,9 +826,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { match terminator.kind { TerminatorKind::Drop { ref place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = self - .instance - .subst_mir(tcx, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty)); + let ty = self.instance.instantiate_mir( + tcx, + ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) { self.cost += CALL_PENALTY; if let UnwindAction::Cleanup(_) = unwind { @@ -824,7 +840,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { - let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.literal.ty())); + let fn_ty = + self.instance.instantiate_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty())); self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { // Don't give intrinsics the extra penalty for calls INSTR_COST diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 822634129fc2b..d30e0bad81301 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -44,7 +44,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( ) -> bool { trace!(%caller); for &(callee, args) in tcx.mir_inliner_callees(caller.def) { - let Ok(args) = caller.try_subst_mir_and_normalize_erasing_regions( + let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, param_env, ty::EarlyBinder::bind(args), diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 6e191b285be9b..a6ef2e11aa828 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -104,7 +104,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { fn try_eval_bool(&self, a: &Operand<'_>) -> Option { let a = a.constant()?; - if a.literal.ty().is_bool() { a.literal.try_to_bool() } else { None } + if a.const_.ty().is_bool() { a.const_.try_to_bool() } else { None } } /// Transform "&(*a)" ==> "a". @@ -136,8 +136,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { return; } - let literal = ConstantKind::from_ty_const(len, self.tcx); - let constant = Constant { span: source_info.span, literal, user_ty: None }; + let const_ = Const::from_ty_const(len, self.tcx); + let constant = ConstOperand { span: source_info.span, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index fc49c9ba348d2..886ff760481e0 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -54,11 +54,8 @@ impl EnumSizeOpt { let layout = tcx.layout_of(param_env.and(ty)).ok()?; let variants = match &layout.variants { Variants::Single { .. } => return None, - Variants::Multiple { tag_encoding, .. } - if matches!(tag_encoding, TagEncoding::Niche { .. }) => - { - return None; - } + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None, + Variants::Multiple { variants, .. } if variants.len() <= 1 => return None, Variants::Multiple { variants, .. } => variants, }; @@ -149,10 +146,10 @@ impl EnumSizeOpt { }; let place = Place::from(size_array_local); - let constant_vals = Constant { + let constant_vals = ConstOperand { span, user_ty: None, - literal: ConstantKind::Val( + const_: Const::Val( ConstValue::Indirect { alloc_id, offset: Size::ZERO }, tmp_ty, ), diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 70d4ea74d1a71..c42888d8791e9 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -31,9 +31,9 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{ - traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, - MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, - Statement, StatementKind, TerminatorKind, START_BLOCK, + traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, + LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, + SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; @@ -54,6 +54,7 @@ mod check_packed_ref; pub mod check_unsafety; mod remove_place_mention; // This pass is public to allow external drivers to perform MIR cleanup +mod add_subtyping_projections; pub mod cleanup_post_borrowck; mod const_debuginfo; mod const_goto; @@ -76,6 +77,7 @@ mod errors; mod ffi_unwind_calls; mod function_item_references; mod generator; +mod gvn; pub mod inline; mod instsimplify; mod large_enums; @@ -149,14 +151,14 @@ fn remap_mir_for_const_eval_select<'tcx>( let terminator = bb.terminator.as_mut().expect("invalid terminator"); match terminator.kind { TerminatorKind::Call { - func: Operand::Constant(box Constant { ref literal, .. }), + func: Operand::Constant(box ConstOperand { ref const_, .. }), ref mut args, destination, target, unwind, fn_span, .. - } if let ty::FnDef(def_id, _) = *literal.ty().kind() + } if let ty::FnDef(def_id, _) = *const_.ty().kind() && tcx.item_name(def_id) == sym::const_eval_select && tcx.is_intrinsic(def_id) => { @@ -343,7 +345,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { let body = match tcx.hir().body_const_context(def) { // consts and statics do not have `optimized_mir`, so we can steal the body instead of // cloning it. - Some(hir::ConstContext::Const | hir::ConstContext::Static(_)) => body.steal(), + Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(), Some(hir::ConstContext::ConstFn) => body.borrow().clone(), None => bug!("`mir_for_ctfe` called on non-const {def:?}"), }; @@ -358,9 +360,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't /// end up missing the source MIR due to stealing happening. fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { - if tcx.sess.opts.unstable_opts.drop_tracking_mir - && let DefKind::Generator = tcx.def_kind(def) - { + if let DefKind::Generator = tcx.def_kind(def) { tcx.ensure_with_value().mir_generator_witnesses(def); } let mir_borrowck = tcx.mir_borrowck(def); @@ -481,6 +481,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ // These next passes must be executed together &add_call_guards::CriticalCallEdges, + &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too. + &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer // necessary as well as well as forcing any call in a non-unwinding @@ -527,7 +529,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { body, &[ &check_alignment::CheckAlignment, - &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, @@ -551,6 +552,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // latter pass will leverage the created opportunities. &separate_const_switch::SeparateConstSwitch, &const_prop::ConstProp, + &gvn::GVN, &dataflow_const_prop::DataflowConstProp, // // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0. @@ -611,6 +613,15 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { return body; } + // If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable + // predicates, it will shrink the MIR to a single `unreachable` terminator. + // More generally, if MIR is a lone `unreachable`, there is nothing to optimize. + if let TerminatorKind::Unreachable = body.basic_blocks[START_BLOCK].terminator().kind + && body.basic_blocks[START_BLOCK].statements.is_empty() + { + return body; + } + run_optimization_passes(tcx, &mut body); body diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 13277d62bf4c9..22f9c6f4f8556 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -2,9 +2,8 @@ use crate::MirPass; use rustc_middle::mir::*; -use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::symbol::sym; use rustc_target::abi::{FieldIdx, VariantIdx}; pub struct LowerIntrinsics; @@ -16,12 +15,10 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { let terminator = block.terminator.as_mut().unwrap(); if let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind + && let ty::FnDef(def_id, generic_args) = *func.ty(local_decls, tcx).kind() + && tcx.is_intrinsic(def_id) { - let func_ty = func.ty(local_decls, tcx); - let Some((intrinsic_name, generic_args)) = resolve_rust_intrinsic(tcx, func_ty) - else { - continue; - }; + let intrinsic_name = tcx.item_name(def_id); match intrinsic_name { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; @@ -32,10 +29,10 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::Use(Operand::Constant(Box::new(Constant { + Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: terminator.source_info.span, user_ty: None, - literal: ConstantKind::zero_sized(tcx.types.unit), + const_: Const::zero_sized(tcx.types.unit), }))), ))), }); @@ -309,15 +306,3 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { } } } - -fn resolve_rust_intrinsic<'tcx>( - tcx: TyCtxt<'tcx>, - func_ty: Ty<'tcx>, -) -> Option<(Symbol, GenericArgsRef<'tcx>)> { - if let ty::FnDef(def_id, args) = *func_ty.kind() { - if tcx.is_intrinsic(def_id) { - return Some((tcx.item_name(def_id), args)); - } - } - None -} diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index b7cc0db95597d..ac52f0ae11248 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -34,67 +34,44 @@ pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -struct SliceLenPatchInformation<'tcx> { - add_statement: Statement<'tcx>, - new_terminator_kind: TerminatorKind<'tcx>, -} - fn lower_slice_len_call<'tcx>( tcx: TyCtxt<'tcx>, block: &mut BasicBlockData<'tcx>, local_decls: &IndexSlice>, slice_len_fn_item_def_id: DefId, ) { - let mut patch_found: Option> = None; - let terminator = block.terminator(); - match &terminator.kind { - TerminatorKind::Call { - func, - args, - destination, - target: Some(bb), - call_source: CallSource::Normal, - .. - } => { - // some heuristics for fast rejection - if args.len() != 1 { - return; - } - let Some(arg) = args[0].place() else { return }; - let func_ty = func.ty(local_decls, tcx); - match func_ty.kind() { - ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => { - // perform modifications - // from something like `_5 = core::slice::::len(move _6) -> bb1` - // into: - // ``` - // _5 = Len(*_6) - // goto bb1 - // ``` + if let TerminatorKind::Call { + func, + args, + destination, + target: Some(bb), + call_source: CallSource::Normal, + .. + } = &terminator.kind + // some heuristics for fast rejection + && let [arg] = &args[..] + && let Some(arg) = arg.place() + && let ty::FnDef(fn_def_id, _) = func.ty(local_decls, tcx).kind() + && *fn_def_id == slice_len_fn_item_def_id + { + // perform modifications from something like: + // _5 = core::slice::::len(move _6) -> bb1 + // into: + // _5 = Len(*_6) + // goto bb1 - // make new RValue for Len - let deref_arg = tcx.mk_place_deref(arg); - let r_value = Rvalue::Len(deref_arg); - let len_statement_kind = - StatementKind::Assign(Box::new((*destination, r_value))); - let add_statement = - Statement { kind: len_statement_kind, source_info: terminator.source_info }; + // make new RValue for Len + let deref_arg = tcx.mk_place_deref(arg); + let r_value = Rvalue::Len(deref_arg); + let len_statement_kind = + StatementKind::Assign(Box::new((*destination, r_value))); + let add_statement = + Statement { kind: len_statement_kind, source_info: terminator.source_info }; - // modify terminator into simple Goto - let new_terminator_kind = TerminatorKind::Goto { target: *bb }; - - let patch = SliceLenPatchInformation { add_statement, new_terminator_kind }; - - patch_found = Some(patch); - } - _ => {} - } - } - _ => {} - } + // modify terminator into simple Goto + let new_terminator_kind = TerminatorKind::Goto { target: *bb }; - if let Some(SliceLenPatchInformation { add_statement, new_terminator_kind }) = patch_found { block.statements.push(add_statement); block.terminator_mut().kind = new_terminator_kind; } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index bc29fb8ded16a..3dc627b614601 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -98,10 +98,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))), StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s - && f_c.literal.ty().is_bool() - && s_c.literal.ty().is_bool() - && f_c.literal.try_eval_bool(tcx, param_env).is_some() - && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {} + && f_c.const_.ty().is_bool() + && s_c.const_.ty().is_bool() + && f_c.const_.try_eval_bool(tcx, param_env).is_some() + && s_c.const_.try_eval_bool(tcx, param_env).is_some() => {} // Otherwise we cannot optimize. Try another block. _ => continue 'outer, @@ -128,8 +128,8 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))), ) => { // From earlier loop we know that we are dealing with bool constants only: - let f_b = f_c.literal.try_eval_bool(tcx, param_env).unwrap(); - let s_b = s_c.literal.try_eval_bool(tcx, param_env).unwrap(); + let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap(); + let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap(); if f_b == s_b { // Same value in both blocks. Use statement as is. (*f).clone() diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 1b846987d38b6..d1a4b26a0466c 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -90,10 +90,10 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { && let [PlaceElem::Deref] = &place.projection[..] && let Some(len) = self.slice_lengths[place.local] { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, - literal: ConstantKind::from_ty_const(len, self.tcx), + const_: Const::from_ty_const(len, self.tcx), }))); } self.super_rvalue(rvalue, loc); diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 49a940b57799c..67941cf439525 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -108,7 +108,7 @@ enum Value<'tcx> { } /// For each local, save the place corresponding to `*local`. -#[instrument(level = "trace", skip(tcx, body))] +#[instrument(level = "trace", skip(tcx, body, ssa))] fn compute_replacement<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index dcc4cd85cda93..a34d4b0276483 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -62,12 +62,12 @@ impl<'tcx> Replacer<'_, 'tcx> { layout.is_zst() } - fn make_zst(&self, ty: Ty<'tcx>) -> Constant<'tcx> { + fn make_zst(&self, ty: Ty<'tcx>) -> ConstOperand<'tcx> { debug_assert!(self.known_to_be_zst(ty)); - Constant { + ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, - literal: ConstantKind::Val(ConstValue::ZeroSized, ty), + const_: Const::Val(ConstValue::ZeroSized, ty), } } } diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index 243cb463560e4..abde6a47e83aa 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,27 +1,27 @@ use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{Constant, ConstantKind, Location}; +use rustc_middle::mir::{Const, ConstOperand, Location}; use rustc_middle::ty::ConstKind; pub struct RequiredConstsVisitor<'a, 'tcx> { - required_consts: &'a mut Vec>, + required_consts: &'a mut Vec>, } impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { - pub fn new(required_consts: &'a mut Vec>) -> Self { + pub fn new(required_consts: &'a mut Vec>) -> Self { RequiredConstsVisitor { required_consts } } } impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { - fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { - let literal = constant.literal; - match literal { - ConstantKind::Ty(c) => match c.kind() { + fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) { + let const_ = constant.const_; + match const_ { + Const::Ty(c) => match c.kind() { ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {} _ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c), }, - ConstantKind::Unevaluated(..) => self.required_consts.push(*constant), - ConstantKind::Val(..) => {} + Const::Unevaluated(..) => self.required_consts.push(*constant), + Const::Val(..) => {} } } } diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 23442f8b97b7e..1626cf3c035e6 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -8,16 +8,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; impl<'tcx> MirPass<'tcx> for RevealAll { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 3 || super::inline::Inline.is_enabled(sess) - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // Do not apply this transformation to generators. - if body.generator.is_some() { - return; - } - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body); } @@ -35,13 +26,38 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { } #[inline] - fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _: Location) { + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + _context: PlaceContext, + _location: Location, + ) { + // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. + if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { + return; + } + // `OpaqueCast` projections are only needed if there are opaque types on which projections are performed. + // After the `RevealAll` pass, all opaque types are replaced with their hidden types, so we don't need these + // projections anymore. + place.projection = self.tcx.mk_place_elems( + &place + .projection + .into_iter() + .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) + .collect::>(), + ); + self.super_place(place, _context, _location); + } + + #[inline] + fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) { - constant.literal = c; + if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) { + constant.const_ = c; } + self.super_constant(constant, location); } #[inline] diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e1000d9693239..e9895d97dfefa 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -497,10 +497,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { // `func == Clone::clone(&ty) -> ty` let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]); - let func = Operand::Constant(Box::new(Constant { + let func = Operand::Constant(Box::new(ConstOperand { span: self.span, user_ty: None, - literal: ConstantKind::zero_sized(func_ty), + const_: Const::zero_sized(func_ty), })); let ref_loc = self.make_place( @@ -764,10 +764,10 @@ fn build_call_shim<'tcx>( CallKind::Direct(def_id) => { let ty = tcx.type_of(def_id).instantiate_identity(); ( - Operand::Constant(Box::new(Constant { + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, - literal: ConstantKind::zero_sized(ty), + const_: Const::zero_sized(ty), })), rcvr.into_iter().collect::>(), ) diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b7a51cfd61966..73dae04435530 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -29,6 +29,7 @@ use crate::MirPass; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -345,24 +346,22 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let basic_blocks = body.basic_blocks.as_mut(); let source_scopes = &body.source_scopes; - let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); - let mut used_blocks = 0; - for alive_index in reachable.iter() { - let alive_index = alive_index.index(); - replacements[alive_index] = BasicBlock::new(used_blocks); - if alive_index != used_blocks { - // Swap the next alive block data with the current available slot. Since - // alive_index is non-decreasing this is a valid operation. - basic_blocks.raw.swap(alive_index, used_blocks); - } - used_blocks += 1; - } - if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, source_scopes, used_blocks); + save_unreachable_coverage(basic_blocks, source_scopes, &reachable); } - basic_blocks.raw.truncate(used_blocks); + let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); + let mut orig_index = 0; + let mut used_index = 0; + basic_blocks.raw.retain(|_| { + let keep = reachable.contains(BasicBlock::new(orig_index)); + if keep { + replacements[orig_index] = BasicBlock::new(used_index); + used_index += 1; + } + orig_index += 1; + keep + }); for block in basic_blocks { for target in block.terminator_mut().successors_mut() { @@ -404,11 +403,12 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn save_unreachable_coverage( basic_blocks: &mut IndexSlice>, source_scopes: &IndexSlice>, - first_dead_block: usize, + reachable: &BitSet, ) { // Identify instances that still have some live coverage counters left. let mut live = FxHashSet::default(); - for basic_block in &basic_blocks.raw[0..first_dead_block] { + for bb in reachable.iter() { + let basic_block = &basic_blocks[bb]; for statement in &basic_block.statements { let StatementKind::Coverage(coverage) = &statement.kind else { continue }; let CoverageKind::Counter { .. } = coverage.kind else { continue }; @@ -417,7 +417,8 @@ fn save_unreachable_coverage( } } - for block in &mut basic_blocks.raw[..first_dead_block] { + for bb in reachable.iter() { + let block = &mut basic_blocks[bb]; for statement in &mut block.statements { let StatementKind::Coverage(_) = &statement.kind else { continue }; let instance = statement.source_info.scope.inlined_instance(source_scopes); @@ -433,24 +434,30 @@ fn save_unreachable_coverage( // Retain coverage for instances that still have some live counters left. let mut retained_coverage = Vec::new(); - for dead_block in &basic_blocks.raw[first_dead_block..] { + for dead_block in basic_blocks.indices() { + if reachable.contains(dead_block) { + continue; + } + let dead_block = &basic_blocks[dead_block]; for statement in &dead_block.statements { let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - let Some(code_region) = &coverage.code_region else { continue }; + if coverage.code_regions.is_empty() { + continue; + }; let instance = statement.source_info.scope.inlined_instance(source_scopes); if live.contains(&instance) { - retained_coverage.push((statement.source_info, code_region.clone())); + retained_coverage.push((statement.source_info, coverage.code_regions.clone())); } } } let start_block = &mut basic_blocks[START_BLOCK]; start_block.statements.extend(retained_coverage.into_iter().map( - |(source_info, code_region)| Statement { + |(source_info, code_regions)| Statement { source_info, kind: StatementKind::Coverage(Box::new(Coverage { kind: CoverageKind::Unreachable, - code_region: Some(code_region), + code_regions, })), }, )); diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 1ff488169864b..b508cd1c9cc53 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -23,7 +23,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), ref targets, .. } => { - let constant = c.literal.try_eval_bits(tcx, param_env, c.ty()); + let constant = c.const_.try_eval_bits(tcx, param_env); if let Some(constant) = constant { let target = targets.target_for_value(constant); TerminatorKind::Goto { target } @@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { } TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } => match c.literal.try_eval_bool(tcx, param_env) { + } => match c.const_.try_eval_bool(tcx, param_env) { Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 113ca2fc5ada5..1a8cfc411784f 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -206,12 +206,12 @@ fn find_branch_value_info<'tcx>( match (left, right) { (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { - let branch_value_ty = branch_value.literal.ty(); + let branch_value_ty = branch_value.const_.ty(); // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats if !branch_value_ty.is_integral() && !branch_value_ty.is_char() { return None; }; - let branch_value_scalar = branch_value.literal.try_to_scalar()?; + let branch_value_scalar = branch_value.const_.try_to_scalar()?; Some((branch_value_scalar, branch_value_ty, *to_switch_on)) } _ => None, diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 04bc461c815cd..fad58930e3a8a 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -13,10 +13,9 @@ use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -#[derive(Debug)] pub struct SsaLocals { /// Assignments to each local. This defines whether the local is SSA. - assignments: IndexVec>, + assignments: IndexVec>, /// We visit the body in reverse postorder, to ensure each local is assigned before it is used. /// We remember the order in which we saw the assignments to compute the SSA values in a single /// pass. @@ -28,65 +27,24 @@ pub struct SsaLocals { direct_uses: IndexVec, } -/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to -/// actually compute dominators, we can just compare block indices because bb0 is always the first -/// block, and in any body all other blocks are always dominated by bb0. -struct SmallDominators<'a> { - inner: Option<&'a Dominators>, -} - -impl SmallDominators<'_> { - fn dominates(&self, first: Location, second: Location) -> bool { - if first.block == second.block { - first.statement_index <= second.statement_index - } else if let Some(inner) = &self.inner { - inner.dominates(first.block, second.block) - } else { - first.block < second.block - } - } - - fn check_dominates(&mut self, set: &mut Set1, loc: Location) { - let assign_dominates = match *set { - Set1::Empty | Set1::Many => false, - Set1::One(LocationExtended::Arg) => true, - Set1::One(LocationExtended::Plain(assign)) => { - self.dominates(assign.successor_within_block(), loc) - } - }; - // We are visiting a use that is not dominated by an assignment. - // Either there is a cycle involved, or we are reading for uninitialized local. - // Bail out. - if !assign_dominates { - *set = Set1::Many; - } - } -} - impl SsaLocals { pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls); - let dominators = - if body.basic_blocks.len() > 2 { Some(body.basic_blocks.dominators()) } else { None }; - let dominators = SmallDominators { inner: dominators }; + let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses }; for local in body.args_iter() { - visitor.assignments[local] = Set1::One(LocationExtended::Arg); + visitor.assignments[local] = Set1::One(DefLocation::Argument); } - if body.basic_blocks.len() > 2 { - for (bb, data) in traversal::reverse_postorder(body) { - visitor.visit_basic_block_data(bb, data); - } - } else { - for (bb, data) in body.basic_blocks.iter_enumerated() { - visitor.visit_basic_block_data(bb, data); - } + // For SSA assignments, a RPO visit will see the assignment before it sees any use. + // We only visit reachable nodes: computing `dominates` on an unreachable node ICEs. + for (bb, data) in traversal::reverse_postorder(body) { + visitor.visit_basic_block_data(bb, data); } for var_debug_info in &body.var_debug_info { @@ -129,12 +87,24 @@ impl SsaLocals { self.direct_uses[local] } + pub fn assignment_dominates( + &self, + dominators: &Dominators, + local: Local, + location: Location, + ) -> bool { + match self.assignments[local] { + Set1::One(def) => def.dominates(location, dominators), + _ => false, + } + } + pub fn assignments<'a, 'tcx>( &'a self, body: &'a Body<'tcx>, ) -> impl Iterator, Location)> + 'a { self.assignment_order.iter().filter_map(|&local| { - if let Set1::One(LocationExtended::Plain(loc)) = self.assignments[local] { + if let Set1::One(DefLocation::Body(loc)) = self.assignments[local] { // `loc` must point to a direct assignment to `local`. let Either::Left(stmt) = body.stmt_at(loc) else { bug!() }; let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() }; @@ -146,6 +116,24 @@ impl SsaLocals { }) } + pub fn for_each_assignment_mut<'tcx>( + &self, + basic_blocks: &mut BasicBlocks<'tcx>, + mut f: impl FnMut(Local, &mut Rvalue<'tcx>, Location), + ) { + for &local in &self.assignment_order { + if let Set1::One(DefLocation::Body(loc)) = self.assignments[local] { + // `loc` must point to a direct assignment to `local`. + let bbs = basic_blocks.as_mut_preserves_cfg(); + let bb = &mut bbs[loc.block]; + let stmt = &mut bb.statements[loc.statement_index]; + let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { bug!() }; + assert_eq!(target.as_local(), Some(local)); + f(local, rvalue, loc) + } + } + } + /// Compute the equivalence classes for locals, based on copy statements. /// /// The returned vector maps each local to the one it copies. In the following case: @@ -192,19 +180,29 @@ impl SsaLocals { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum LocationExtended { - Plain(Location), - Arg, -} - struct SsaVisitor<'a> { - dominators: SmallDominators<'a>, - assignments: IndexVec>, + dominators: &'a Dominators, + assignments: IndexVec>, assignment_order: Vec, direct_uses: IndexVec, } +impl SsaVisitor<'_> { + fn check_dominates(&mut self, local: Local, loc: Location) { + let set = &mut self.assignments[local]; + let assign_dominates = match *set { + Set1::Empty | Set1::Many => false, + Set1::One(def) => def.dominates(loc, self.dominators), + }; + // We are visiting a use that is not dominated by an assignment. + // Either there is a cycle involved, or we are reading for uninitialized local. + // Bail out. + if !assign_dominates { + *set = Set1::Many; + } + } +} + impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { @@ -222,7 +220,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { self.assignments[local] = Set1::Many; } PlaceContext::NonMutatingUse(_) => { - self.dominators.check_dominates(&mut self.assignments[local], loc); + self.check_dominates(local, loc); self.direct_uses[local] += 1; } PlaceContext::NonUse(_) => {} @@ -237,7 +235,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { let new_ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy); self.visit_projection(place.as_ref(), new_ctxt, loc); - self.dominators.check_dominates(&mut self.assignments[place.local], loc); + self.check_dominates(place.local, loc); } return; } else { @@ -248,7 +246,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, loc: Location) { if let Some(local) = place.as_local() { - self.assignments[local].insert(LocationExtended::Plain(loc)); + self.assignments[local].insert(DefLocation::Body(loc)); if let Set1::One(_) = self.assignments[local] { // Only record if SSA-like, to avoid growing the vector needlessly. self.assignment_order.push(local); @@ -324,7 +322,7 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) { #[derive(Debug)] pub(crate) struct StorageLiveLocals { /// Set of "StorageLive" statements for each local. - storage_live: IndexVec>, + storage_live: IndexVec>, } impl StorageLiveLocals { @@ -334,13 +332,13 @@ impl StorageLiveLocals { ) -> StorageLiveLocals { let mut storage_live = IndexVec::from_elem(Set1::Empty, &body.local_decls); for local in always_storage_live_locals.iter() { - storage_live[local] = Set1::One(LocationExtended::Arg); + storage_live[local] = Set1::One(DefLocation::Argument); } for (block, bbdata) in body.basic_blocks.iter_enumerated() { for (statement_index, statement) in bbdata.statements.iter().enumerate() { if let StatementKind::StorageLive(local) = statement.kind { storage_live[local] - .insert(LocationExtended::Plain(Location { block, statement_index })); + .insert(DefLocation::Body(Location { block, statement_index })); } } } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 092bcb5c97930..cb028a92d49b2 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -30,22 +30,17 @@ fn get_switched_on_type<'tcx>( let terminator = block_data.terminator(); // Only bother checking blocks which terminate by switching on a local. - if let Some(local) = get_discriminant_local(&terminator.kind) { - let stmt_before_term = (!block_data.statements.is_empty()) - .then(|| &block_data.statements[block_data.statements.len() - 1].kind); - - if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term - { - if l.as_local() == Some(local) { - let ty = place.ty(body, tcx).ty; - if ty.is_enum() { - return Some(ty); - } - } - } + if let Some(local) = get_discriminant_local(&terminator.kind) + && let [.., stmt_before_term] = &block_data.statements[..] + && let StatementKind::Assign(box (l, Rvalue::Discriminant(place))) = stmt_before_term.kind + && l.as_local() == Some(local) + && let ty = place.ty(body, tcx).ty + && ty.is_enum() + { + Some(ty) + } else { + None } - - None } fn variant_discriminants<'tcx>( diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index bd1724bf84241..0b9311a20efa3 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -13,7 +13,11 @@ pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable. - sess.mir_opt_level() >= 2 + + // FIXME(#116171) Coverage gets confused by MIR passes that can remove all + // coverage statements from an instrumented function. This pass can be + // re-enabled when coverage codegen is robust against that happening. + sess.mir_opt_level() >= 2 && !sess.instrument_coverage() } fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 2b7d9bd341393..cf23d79afaf16 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -7,8 +7,6 @@ monomorphize_couldnt_dump_mono_stats = monomorphize_encountered_error_while_instantiating = the above error was encountered while instantiating `{$formatted_item}` -monomorphize_fatal_error = {$error_message} - monomorphize_large_assignments = moving {$size} bytes .label = value moved from here diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index c8b7210775658..6ea177bb6ea9a 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -432,7 +432,7 @@ fn collect_items_rec<'tcx>( hir::InlineAsmOperand::SymFn { anon_const } => { let fn_ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); - visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items, &[]); + visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items); } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { let instance = Instance::mono(tcx, *def_id); @@ -593,11 +593,9 @@ struct MirUsedCollector<'a, 'tcx> { instance: Instance<'tcx>, /// Spans for move size lints already emitted. Helps avoid duplicate lints. move_size_spans: Vec, - /// If true, we should temporarily skip move size checks, because we are - /// processing an operand to a `skip_move_check_fns` function call. - skip_move_size_check: bool, + visiting_call_terminator: bool, /// Set of functions for which it is OK to move large data into. - skip_move_check_fns: Vec, + skip_move_check_fns: Option>, } impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { @@ -606,14 +604,27 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { T: TypeFoldable>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), ) } - fn check_move_size(&mut self, limit: usize, operand: &mir::Operand<'tcx>, location: Location) { + fn check_operand_move_size(&mut self, operand: &mir::Operand<'tcx>, location: Location) { + let limit = self.tcx.move_size_limit().0; + if limit == 0 { + return; + } + + // This function is called by visit_operand() which visits _all_ + // operands, including TerminatorKind::Call operands. But if + // check_fn_args_move_size() has been called, the operands have already + // been visited. Do not visit them again. + if self.visiting_call_terminator { + return; + } + let limit = Size::from_bytes(limit); let ty = operand.ty(self.body, self.tcx); let ty = self.monomorphize(ty); @@ -651,6 +662,38 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { ); self.move_size_spans.push(source_info.span); } + + fn check_fn_args_move_size( + &mut self, + callee_ty: Ty<'tcx>, + args: &[mir::Operand<'tcx>], + location: Location, + ) { + let limit = self.tcx.move_size_limit(); + if limit.0 == 0 { + return; + } + + if args.is_empty() { + return; + } + + // Allow large moves into container types that themselves are cheap to move + let ty::FnDef(def_id, _) = *callee_ty.kind() else { + return; + }; + if self + .skip_move_check_fns + .get_or_insert_with(|| build_skip_move_check_fns(self.tcx)) + .contains(&def_id) + { + return; + } + + for arg in args { + self.check_operand_move_size(arg, location); + } + } } impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { @@ -696,14 +739,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { ) => { let fn_ty = operand.ty(self.body, self.tcx); let fn_ty = self.monomorphize(fn_ty); - visit_fn_use( - self.tcx, - fn_ty, - false, - span, - &mut self.output, - &self.skip_move_check_fns, - ); + visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output); } mir::Rvalue::Cast( mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)), @@ -746,20 +782,20 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily /// work, as some constants cannot be represented in the type system. #[instrument(skip(self), level = "debug")] - fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) { - let literal = self.monomorphize(constant.literal); + fn visit_constant(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) { + let const_ = self.monomorphize(constant.const_); let param_env = ty::ParamEnv::reveal_all(); - let val = match literal.eval(self.tcx, param_env, None) { + let val = match const_.eval(self.tcx, param_env, None) { Ok(v) => v, Err(ErrorHandled::Reported(..)) => return, Err(ErrorHandled::TooGeneric(..)) => span_bug!( self.body.source_info(location).span, "collection encountered polymorphic constant: {:?}", - literal + const_ ), }; collect_const_value(self.tcx, val, self.output); - MirVisitor::visit_ty(self, literal.ty(), TyContext::Location(location)); + MirVisitor::visit_ty(self, const_.ty(), TyContext::Location(location)); } fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { @@ -775,17 +811,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { }; match terminator.kind { - mir::TerminatorKind::Call { ref func, .. } => { + mir::TerminatorKind::Call { ref func, ref args, .. } => { let callee_ty = func.ty(self.body, tcx); let callee_ty = self.monomorphize(callee_ty); - self.skip_move_size_check = visit_fn_use( - self.tcx, - callee_ty, - true, - source, - &mut self.output, - &self.skip_move_check_fns, - ) + self.check_fn_args_move_size(callee_ty, args, location); + visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; @@ -796,8 +826,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { for op in operands { match *op { mir::InlineAsmOperand::SymFn { ref value } => { - let fn_ty = self.monomorphize(value.literal.ty()); - visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]); + let fn_ty = self.monomorphize(value.const_.ty()); + visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output); } mir::InlineAsmOperand::SymStatic { def_id } => { let instance = Instance::mono(self.tcx, def_id); @@ -835,16 +865,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { push_mono_lang_item(self, reason.lang_item()); } + self.visiting_call_terminator = matches!(terminator.kind, mir::TerminatorKind::Call { .. }); self.super_terminator(terminator, location); - self.skip_move_size_check = false; + self.visiting_call_terminator = false; } fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { self.super_operand(operand, location); - let move_size_limit = self.tcx.move_size_limit().0; - if move_size_limit > 0 && !self.skip_move_size_check { - self.check_move_size(move_size_limit, operand, location); - } + self.check_operand_move_size(operand, location); } fn visit_local( @@ -873,11 +901,8 @@ fn visit_fn_use<'tcx>( is_direct_call: bool, source: Span, output: &mut MonoItems<'tcx>, - skip_move_check_fns: &[DefId], -) -> bool { - let mut skip_move_size_check = false; +) { if let ty::FnDef(def_id, args) = *ty.kind() { - skip_move_size_check = skip_move_check_fns.contains(&def_id); let instance = if is_direct_call { ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args) } else { @@ -888,7 +913,6 @@ fn visit_fn_use<'tcx>( }; visit_instance_use(tcx, instance, is_direct_call, source, output); } - skip_move_size_check } fn visit_instance_use<'tcx>( @@ -1395,6 +1419,29 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> return None; } +fn build_skip_move_check_fns(tcx: TyCtxt<'_>) -> Vec { + let mut skip_move_check_fns = vec![]; + add_assoc_fn( + tcx, + tcx.lang_items().owned_box(), + Ident::from_str("new"), + &mut skip_move_check_fns, + ); + add_assoc_fn( + tcx, + tcx.get_diagnostic_item(sym::Arc), + Ident::from_str("new"), + &mut skip_move_check_fns, + ); + add_assoc_fn( + tcx, + tcx.get_diagnostic_item(sym::Rc), + Ident::from_str("new"), + &mut skip_move_check_fns, + ); + skip_move_check_fns +} + /// Scans the MIR in order to find function calls, closures, and drop-glue. #[instrument(skip(tcx, output), level = "debug")] fn collect_used_items<'tcx>( @@ -1404,36 +1451,16 @@ fn collect_used_items<'tcx>( ) { let body = tcx.instance_mir(instance.def); - let mut skip_move_check_fns = vec![]; - if tcx.move_size_limit().0 > 0 { - add_assoc_fn( - tcx, - tcx.lang_items().owned_box(), - Ident::from_str("new"), - &mut skip_move_check_fns, - ); - add_assoc_fn( - tcx, - tcx.get_diagnostic_item(sym::Arc), - Ident::from_str("new"), - &mut skip_move_check_fns, - ); - add_assoc_fn( - tcx, - tcx.get_diagnostic_item(sym::Rc), - Ident::from_str("new"), - &mut skip_move_check_fns, - ); - } - + // Here we rely on the visitor also visiting `required_consts`, so that we evaluate them + // and abort compilation if any of them errors. MirUsedCollector { tcx, body: &body, output, instance, move_size_spans: vec![], - skip_move_size_check: false, - skip_move_check_fns, + visiting_call_terminator: false, + skip_move_check_fns: None, } .visit_body(&body); } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index c993e64477b07..1d8cbe0e21b7d 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -647,7 +647,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // parameters, but the self-type of their impl block do will fail to normalize. if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() { // This is a method within an impl, find out what the self-type is: - let impl_self_ty = tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), tcx.type_of(impl_def_id), diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index a8b7a0dbb681f..6c206a6bac8bd 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -9,13 +9,13 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_middle::mir::{ self, visit::{TyContext, Visitor}, - Constant, ConstantKind, Local, LocalDecl, Location, + Local, LocalDecl, Location, }; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}, - Const, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, + GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, }; use rustc_span::symbol::sym; use std::ops::ControlFlow; @@ -143,7 +143,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -261,12 +261,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.super_local_decl(local, local_decl); } - fn visit_constant(&mut self, ct: &Constant<'tcx>, location: Location) { - match ct.literal { - ConstantKind::Ty(c) => { + fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) { + match ct.const_ { + mir::Const::Ty(c) => { c.visit_with(self); } - ConstantKind::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => { + mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => { // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if let Some(p) = promoted { @@ -280,7 +280,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { Visitor::visit_ty(self, ty, TyContext::Location(location)); } - ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)), + mir::Const::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)), } } @@ -291,7 +291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { if !c.has_non_region_param() { return ControlFlow::Continue(()); } diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index a3433d3d13dba..e25c5c9f27c75 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -26,12 +26,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = typeck_results.closure_size_eval[&closure_def_id]; - let before_feature_tys = tcx.subst_and_normalize_erasing_regions( + let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(before_feature_tys), ); - let after_feature_tys = tcx.subst_and_normalize_erasing_regions( + let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(after_feature_tys), diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 2c4bc7bb5687f..e0778f72bfe6e 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -59,7 +59,6 @@ parse_bare_cr = {$double_quotes -> parse_bare_cr_in_raw_string = bare CR not allowed in raw string -parse_binary_float_literal_not_supported = binary float literal is not supported parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases parse_box_not_pat = expected pattern, found {$descr} @@ -226,6 +225,10 @@ parse_expected_semi_found_str = expected `;`, found `{$token}` parse_expected_statement_after_outer_attr = expected statement after outer attribute +parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$token}` + .label = expected one of `,`, `:`, or `{"}"}` + .ident_label = while parsing this struct field + parse_expected_trait_in_trait_impl_found_type = expected a trait, found type parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements @@ -284,7 +287,6 @@ parse_generics_in_path = unexpected generic arguments in path parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` -parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported parse_if_expression_missing_condition = missing condition for `if` expression .condition_label = expected condition here .block_label = if this block is the condition of the `if` expression, then it must be followed by another block @@ -356,8 +358,6 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style -parse_int_literal_too_large = integer literal is too large - parse_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context .suggestion = wrap this in another block @@ -382,18 +382,8 @@ parse_invalid_dyn_keyword = invalid `dyn` keyword .suggestion = remove this keyword parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` -parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal - .label = invalid suffix `{$suffix}` - .help = valid suffixes are `f32` and `f64` - -parse_invalid_float_literal_width = invalid width `{$width}` for float literal - .help = valid widths are 32 and 64 - parse_invalid_identifier_with_leading_number = identifiers cannot start with a number -parse_invalid_int_literal_width = invalid width `{$width}` for integer literal - .help = valid widths are 8, 16, 32, 64 and 128 - parse_invalid_interpolated_expression = invalid interpolated expression parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid @@ -412,14 +402,6 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` -parse_invalid_num_literal_base_prefix = invalid base prefix for number literal - .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase - .suggestion = try making the prefix lowercase - -parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal - .label = invalid suffix `{$suffix}` - .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) - parse_invalid_unicode_escape = invalid unicode character escape .label = invalid escape .help = unicode escape must {$surrogate -> @@ -509,7 +491,7 @@ parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of parse_maybe_recover_from_bad_qpath_stage_2 = missing angle brackets in associated item path - .suggestion = try: `{$ty}` + .suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths parse_maybe_recover_from_bad_type_plus = expected a path on the left-hand side of `+`, not `{$ty}` @@ -603,13 +585,6 @@ parse_no_brace_unicode_escape = incorrect unicode escape sequence parse_no_digits_literal = no valid digits found for number -parse_non_item_in_item_list = non-item in item list - .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const - .label_list_start = item list starts here - .label_non_item = non-item starts here - .label_list_end = item list ends here - .suggestion_remove_semicolon = consider removing this semicolon - parse_non_string_abi_literal = non-string ABI literal .suggestion = specify the ABI with a string literal @@ -626,7 +601,6 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` -parse_octal_float_literal_not_supported = octal float literal is not supported parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings parse_out_of_range_hex_escape = out of range hex escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 5d3ec68355203..aeb4fd0a304aa 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -59,9 +59,18 @@ pub(crate) enum BadTypePlusSub { #[diag(parse_maybe_recover_from_bad_qpath_stage_2)] pub(crate) struct BadQPathStage2 { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, - pub ty: String, + #[subdiagnostic] + pub wrap: WrapType, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct WrapType { + #[suggestion_part(code = "<")] + pub lo: Span, + #[suggestion_part(code = ">")] + pub hi: Span, } #[derive(Diagnostic)] @@ -421,6 +430,17 @@ pub(crate) struct ExpectedElseBlock { pub condition_start: Span, } +#[derive(Diagnostic)] +#[diag(parse_expected_struct_field)] +pub(crate) struct ExpectedStructField { + #[primary_span] + #[label] + pub span: Span, + pub token: Token, + #[label(parse_ident_label)] + pub ident_span: Span, +} + #[derive(Diagnostic)] #[diag(parse_outer_attribute_not_allowed_on_if_else)] pub(crate) struct OuterAttributeNotAllowedOnIfElse { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 6c8ef34063f87..06b1b1523edbd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -16,7 +16,7 @@ use crate::errors::{ StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, - UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, + UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::fluent_generated as fluent; @@ -1589,10 +1589,9 @@ impl<'a> Parser<'a> { self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; path.span = ty_span.to(self.prev_token.span); - let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty)); self.sess.emit_err(BadQPathStage2 { - span: path.span, - ty: format!("<{}>::{}", ty_str, pprust::path_to_string(&path)), + span: ty_span, + wrap: WrapType { lo: ty_span.shrink_to_lo(), hi: ty_span.shrink_to_hi() }, }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f4cee3a661e65..91bb2d9eb666f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2834,7 +2834,7 @@ impl<'a> Parser<'a> { )?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; - let mut cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?; + let mut cond = this.parse_match_guard_condition()?; CondChecker { parser: this, forbid_let_reason: None }.visit_expr(&mut cond); @@ -2860,9 +2860,9 @@ impl<'a> Parser<'a> { { err.span_suggestion( this.token.span, - "try using a fat arrow here", + "use a fat arrow to start a match arm", "=>", - Applicability::MaybeIncorrect, + Applicability::MachineApplicable, ); err.emit(); this.bump(); @@ -2979,6 +2979,33 @@ impl<'a> Parser<'a> { }) } + fn parse_match_guard_condition(&mut self) -> PResult<'a, P> { + self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, None).map_err( + |mut err| { + if self.prev_token == token::OpenDelim(Delimiter::Brace) { + let sugg_sp = self.prev_token.span.shrink_to_lo(); + // Consume everything within the braces, let's avoid further parse + // errors. + self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); + let msg = "you might have meant to start a match arm after the match guard"; + if self.eat(&token::CloseDelim(Delimiter::Brace)) { + let applicability = if self.token.kind != token::FatArrow { + // We have high confidence that we indeed didn't have a struct + // literal in the match guard, but rather we had some operation + // that ended in a path, immediately followed by a block that was + // meant to be the match arm. + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability); + } + } + err + }, + ) + } + pub(crate) fn is_builtin(&self) -> bool { self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound) } @@ -3049,9 +3076,10 @@ impl<'a> Parser<'a> { || self.look_ahead(2, |t| t == &token::Colon) && ( // `{ ident: token, ` cannot start a block. - self.look_ahead(4, |t| t == &token::Comma) || - // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`. - self.look_ahead(3, |t| !t.can_begin_type()) + self.look_ahead(4, |t| t == &token::Comma) + // `{ ident: ` cannot start a block unless it's a type ascription + // `ident: Type`. + || self.look_ahead(3, |t| !t.can_begin_type()) ) ) } @@ -3091,6 +3119,7 @@ impl<'a> Parser<'a> { let mut fields = ThinVec::new(); let mut base = ast::StructRest::None; let mut recover_async = false; + let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD); let mut async_block_err = |e: &mut Diagnostic, span: Span| { recover_async = true; @@ -3128,6 +3157,26 @@ impl<'a> Parser<'a> { e.span_label(pth.span, "while parsing this struct"); } + if let Some((ident, _)) = self.token.ident() + && !self.token.is_reserved_ident() + && self.look_ahead(1, |t| { + AssocOp::from_token(&t).is_some() + || matches!(t.kind, token::OpenDelim(_)) + || t.kind == token::Dot + }) + { + // Looks like they tried to write a shorthand, complex expression. + e.span_suggestion_verbose( + self.token.span.shrink_to_lo(), + "try naming a field", + &format!("{ident}: ", ), + Applicability::MaybeIncorrect, + ); + } + if in_if_guard && close_delim == Delimiter::Brace { + return Err(e); + } + if !recover { return Err(e); } @@ -3173,19 +3222,6 @@ impl<'a> Parser<'a> { ",", Applicability::MachineApplicable, ); - } else if is_shorthand - && (AssocOp::from_token(&self.token).is_some() - || matches!(&self.token.kind, token::OpenDelim(_)) - || self.token.kind == token::Dot) - { - // Looks like they tried to write a shorthand, complex expression. - let ident = parsed_field.expect("is_shorthand implies Some").ident; - e.span_suggestion( - ident.span.shrink_to_lo(), - "try naming a field", - &format!("{ident}: "), - Applicability::HasPlaceholders, - ); } } if !recover { @@ -3288,6 +3324,24 @@ impl<'a> Parser<'a> { // Check if a colon exists one ahead. This means we're parsing a fieldname. let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); + // Proactively check whether parsing the field will be incorrect. + let is_wrong = this.token.is_ident() + && !this.token.is_reserved_ident() + && !this.look_ahead(1, |t| { + t == &token::Colon + || t == &token::Eq + || t == &token::Comma + || t == &token::CloseDelim(Delimiter::Brace) + || t == &token::CloseDelim(Delimiter::Parenthesis) + }); + if is_wrong { + return Err(errors::ExpectedStructField { + span: this.look_ahead(1, |t| t.span), + ident_span: this.token.span, + token: this.look_ahead(1, |t| t.clone()), + } + .into_diagnostic(&self.sess.span_diagnostic)); + } let (ident, expr) = if is_shorthand { // Mimic `x: x` for the `x` field shorthand. let ident = this.parse_ident_common(false)?; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad4edaba90b5..cc54cc5bebbdd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -813,7 +813,12 @@ impl<'a> Parser<'a> { fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { let unsafety = self.parse_unsafety(Case::Sensitive); // Parse optional `auto` prefix. - let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; + let is_auto = if self.eat_keyword(kw::Auto) { + self.sess.gated_spans.gate(sym::auto_traits, self.prev_token.span); + IsAuto::Yes + } else { + IsAuto::No + }; self.expect_keyword(kw::Trait)?; let ident = self.parse_ident()?; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index e84d8f5b3582e..6c24646f39a68 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -52,6 +52,7 @@ bitflags::bitflags! { const NO_STRUCT_LITERAL = 1 << 1; const CONST_EXPR = 1 << 2; const ALLOW_LET = 1 << 3; + const IN_IF_GUARD = 1 << 4; } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a25b0f1f8930e..0a64b2f806a5f 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -247,7 +247,7 @@ impl<'a> Parser<'a> { )?; FnRetTy::Ty(ty) } else { - FnRetTy::Default(self.token.span.shrink_to_lo()) + FnRetTy::Default(self.prev_token.span.shrink_to_hi()) }) } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 4f8ce99417a27..25ef5245cf169 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -407,6 +407,10 @@ passes_invalid_stability = .label = invalid stability version .item = the stability attribute annotates this item +passes_lang_item_fn_with_target_feature = + `{$name}` language item function is not allowed to have `#[target_feature]` + .label = `{$name}` language item function is not allowed to have `#[target_feature]` + passes_lang_item_on_incorrect_target = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target} @@ -576,6 +580,8 @@ passes_outside_loop = *[false] {""} } +passes_outside_loop_suggestion = consider labeling this block to be able to break within it + passes_params_not_allowed = referencing function parameters is not allowed in naked functions .help = follow the calling convention in asm block to use parameters @@ -644,6 +650,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_safe_intrinsic = + attribute should be applied to intrinsic functions + .label = not an intrinsic function + passes_rustc_std_internal_symbol = attribute should be applied to functions or statics .label = not a function or static diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 9e4d960af1412..153c39977bb44 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -21,7 +21,7 @@ pub fn test_abi(tcx: TyCtxt<'_>) { DefKind::Fn | DefKind::AssocFn => { dump_abi_of_fn_item(tcx, id, attr); } - DefKind::TyAlias { .. } => { + DefKind::TyAlias => { dump_abi_of_fn_type(tcx, id, attr); } _ => { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2d94354e3e107..52fb193f3da6b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -118,7 +118,7 @@ impl CheckAttrVisitor<'_> { sym::coverage => self.check_coverage(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::marker => self.check_marker(hir_id, attr, span, target), - sym::target_feature => self.check_target_feature(hir_id, attr, span, target), + sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs), sym::thread_local => self.check_thread_local(attr, span, target), sym::track_caller => { self.check_track_caller(hir_id, attr.span, attrs, span, target) @@ -195,6 +195,9 @@ impl CheckAttrVisitor<'_> { | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target), sym::link_ordinal => self.check_link_ordinal(&attr, span, target), sym::rustc_confusables => self.check_confusables(&attr, target), + sym::rustc_safe_intrinsic => { + self.check_rustc_safe_intrinsic(hir_id, attr, span, target) + } _ => true, }; @@ -591,10 +594,36 @@ impl CheckAttrVisitor<'_> { attr: &Attribute, span: Span, target: Target, + attrs: &[Attribute], ) -> bool { match target { - Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + Target::Fn => { + // `#[target_feature]` is not allowed in language items. + if let Some((lang_item, _)) = hir::lang_items::extract(attrs) + // Calling functions with `#[target_feature]` is + // not unsafe on WASM, see #84988 + && !self.tcx.sess.target.is_like_wasm + && !self.tcx.sess.opts.actually_rustdoc + { + let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else { + unreachable!(); + }; + let hir::ItemKind::Fn(sig, _, _) = item.kind else { + // target is `Fn` + unreachable!(); + }; + + self.tcx.sess.emit_err(errors::LangItemWithTargetFeature { + attr_span: attr.span, + name: lang_item, + sig_span: sig.span, + }); + false + } else { + true + } + } + Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, // FIXME: #[target_feature] was previously erroneously allowed on statements and some // crates used this, so only emit a warning. Target::Statement => { @@ -2016,6 +2045,29 @@ impl CheckAttrVisitor<'_> { } } + fn check_rustc_safe_intrinsic( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + let hir = self.tcx.hir(); + + if let Target::ForeignFn = target + && let Some(parent) = hir.opt_parent_id(hir_id) + && let hir::Node::Item(Item { + kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic | Abi::PlatformIntrinsic, .. }, + .. + }) = hir.get(parent) + { + return true; + } + + self.tcx.sess.emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span }); + false + } + fn check_rustc_std_internal_symbol( &self, attr: &Attribute, @@ -2307,7 +2359,10 @@ impl CheckAttrVisitor<'_> { &mut diag, &cause, None, - Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })), + Some(ValuePairs::PolySigs(ExpectedFound { + expected: ty::Binder::dummy(expected_sig), + found: ty::Binder::dummy(sig), + })), terr, false, false, @@ -2318,7 +2373,7 @@ impl CheckAttrVisitor<'_> { let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); self.abort.set(true); } } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 8437e9a40e2a2..6d176af809805 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -193,12 +193,12 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { } fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { - let kind = Some(hir::ConstContext::Const); + let kind = Some(hir::ConstContext::Const { inline: false }); self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); } fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) { - let kind = Some(hir::ConstContext::Const); + let kind = Some(hir::ConstContext::Const { inline: true }); self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block)); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d1c3bcf3839d5..f853039f72ce1 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1,6 +1,7 @@ -// This implements the dead-code warning pass. It follows middle::reachable -// closely. The idea is that all reachable symbols are live, codes called -// from live codes are live, and everything else is dead. +// This implements the dead-code warning pass. +// All reachable symbols are live, code called from live code is live, code with certain lint +// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else +// is dead. use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use itertools::Itertools; @@ -96,7 +97,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias { .. }, def_id) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -747,7 +748,7 @@ fn live_symbols_and_ignored_derived_traits( (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits) } -struct DeadVariant { +struct DeadItem { def_id: LocalDefId, name: Symbol, level: lint::Level, @@ -785,7 +786,13 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes(is_positional) } - fn warn_multiple_dead_codes( + // # Panics + // All `dead_codes` must have the same lint level, otherwise we will intentionally ICE. + // This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s + // first local def id. + // Prefer calling `Self.warn_dead_code` or `Self.warn_dead_code_grouped_by_lint_level` + // since those methods group by lint level before calling this method. + fn lint_at_single_level( &self, dead_codes: &[LocalDefId], participle: &str, @@ -796,6 +803,15 @@ impl<'tcx> DeadVisitor<'tcx> { return; }; let tcx = self.tcx; + + let first_hir_id = tcx.hir().local_def_id_to_hir_id(first_id); + let first_lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, first_hir_id).0; + assert!(dead_codes.iter().skip(1).all(|id| { + let hir_id = tcx.hir().local_def_id_to_hir_id(*id); + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + level == first_lint_level + })); + let names: Vec<_> = dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect(); let spans: Vec<_> = dead_codes @@ -876,31 +892,26 @@ impl<'tcx> DeadVisitor<'tcx> { } }; - self.tcx.emit_spanned_lint( - lint, - tcx.hir().local_def_id_to_hir_id(first_id), - MultiSpan::from_spans(spans), - diag, - ); + self.tcx.emit_spanned_lint(lint, first_hir_id, MultiSpan::from_spans(spans), diag); } - fn warn_dead_fields_and_variants( + fn warn_multiple( &self, def_id: LocalDefId, participle: &str, - dead_codes: Vec, + dead_codes: Vec, is_positional: bool, ) { let mut dead_codes = dead_codes .iter() .filter(|v| !v.name.as_str().starts_with('_')) - .collect::>(); + .collect::>(); if dead_codes.is_empty() { return; } dead_codes.sort_by_key(|v| v.level); for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) { - self.warn_multiple_dead_codes( + self.lint_at_single_level( &group.map(|v| v.def_id).collect::>(), participle, Some(def_id), @@ -910,7 +921,7 @@ impl<'tcx> DeadVisitor<'tcx> { } fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) { - self.warn_multiple_dead_codes(&[id], participle, None, false); + self.lint_at_single_level(&[id], participle, None, false); } fn check_definition(&mut self, def_id: LocalDefId) { @@ -923,7 +934,7 @@ impl<'tcx> DeadVisitor<'tcx> { | DefKind::Fn | DefKind::Static(_) | DefKind::Const - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Enum | DefKind::Union | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), @@ -954,17 +965,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind { let mut dead_items = Vec::new(); for item in impl_item.items { - let did = item.id.owner_id.def_id; - if !visitor.is_live_code(did) { - dead_items.push(did) + let def_id = item.id.owner_id.def_id; + if !visitor.is_live_code(def_id) { + let name = tcx.item_name(def_id.to_def_id()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + + dead_items.push(DeadItem { def_id, name, level }) } } - visitor.warn_multiple_dead_codes( - &dead_items, - "used", - Some(item.owner_id.def_id), - false, - ); + visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, false); } if !live_symbols.contains(&item.owner_id.def_id) { @@ -988,7 +998,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { // Record to group diagnostics. let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; - dead_variants.push(DeadVariant { def_id, name: variant.name, level }); + dead_variants.push(DeadItem { def_id, name: variant.name, level }); continue; } @@ -1013,21 +1023,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { hir_id, ) .0; - Some(DeadVariant { def_id, name: field.name, level }) + Some(DeadItem { def_id, name: field.name, level }) } else { None } }) .collect(); - visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional) + visitor.warn_multiple(def_id, "read", dead_fields, is_positional); } - visitor.warn_dead_fields_and_variants( - item.owner_id.def_id, - "constructed", - dead_variants, - false, - ); + visitor.warn_multiple(item.owner_id.def_id, "constructed", dead_variants, false); } } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 4f71704b8853d..c92d0b878eafb 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -52,31 +52,6 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { configure_main(tcx, &ctxt) } -// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs` -// (with `ast::Item`), so make sure to keep them in sync. -// A small optimization was added so that hir::Item is fetched only when needed. -// An equivalent optimization was not applied to the duplicated code in test_harness.rs. -fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> EntryPointType { - let attrs = ctxt.tcx.hir().attrs(id.hir_id()); - if attr::contains_name(attrs, sym::start) { - EntryPointType::Start - } else if attr::contains_name(attrs, sym::rustc_main) { - EntryPointType::RustcMainAttr - } else { - if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id()) - && name == sym::main { - if at_root { - // This is a top-level function so can be `main`. - EntryPointType::MainNamed - } else { - EntryPointType::OtherMain - } - } else { - EntryPointType::None - } - } -} - fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option { let attrs = ctxt.tcx.hir().attrs(id.hir_id()); attr::find_by_name(attrs, sym).map(|attr| attr.span) @@ -85,7 +60,13 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); - match entry_point_type(ctxt, id, at_root) { + let attrs = ctxt.tcx.hir().attrs(id.hir_id()); + let entry_point_type = rustc_ast::entry::entry_point_type( + attrs, + at_root, + ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), + ); + match entry_point_type { EntryPointType::None => { if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8b65e301b7450..4b27b6d8c3698 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -620,6 +620,15 @@ pub struct RustcAllowConstFnUnstable { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_rustc_safe_intrinsic)] +pub struct RustcSafeIntrinsic { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] pub struct RustcStdInternalSymbol { @@ -808,6 +817,16 @@ pub struct MissingLangItem { pub name: Symbol, } +#[derive(Diagnostic)] +#[diag(passes_lang_item_fn_with_target_feature)] +pub struct LangItemWithTargetFeature { + #[primary_span] + pub attr_span: Span, + pub name: Symbol, + #[label] + pub sig_span: Span, +} + #[derive(Diagnostic)] #[diag(passes_lang_item_on_incorrect_target, code = "E0718")] pub struct LangItemOnIncorrectTarget { @@ -1080,6 +1099,16 @@ pub struct OutsideLoop<'a> { pub span: Span, pub name: &'a str, pub is_break: bool, + #[subdiagnostic] + pub suggestion: Option, +} +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_outside_loop_suggestion, applicability = "maybe-incorrect")] +pub struct OutsideLoopSuggestion { + #[suggestion_part(code = "'block: ")] + pub block_span: Span, + #[suggestion_part(code = " 'block")] + pub break_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 476394f30ccfd..7e83724391836 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -20,7 +20,8 @@ use rustc_hir::lang_items::{extract, GenericRequirement}; use rustc_hir::{LangItem, LanguageItems, Target}; use rustc_middle::ty::TyCtxt; use rustc_session::cstore::ExternCrate; -use rustc_span::{symbol::kw::Empty, Span}; +use rustc_span::symbol::kw::Empty; +use rustc_span::{sym, Span}; use rustc_middle::query::Providers; @@ -157,7 +158,14 @@ impl<'tcx> LanguageItemCollector<'tcx> { self.tcx.hir().get_by_def_id(item_def_id) { let (actual_num, generics_span) = match kind.generics() { - Some(generics) => (generics.params.len(), generics.span), + Some(generics) => ( + generics + .params + .iter() + .filter(|p| !self.tcx.has_attr(p.def_id, sym::rustc_host)) + .count(), + generics.span, + ), None => (0, *item_span), }; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index e3a63f2e00441..2129a98cda3f9 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -23,7 +23,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) { for id in tcx.hir_crate_items(()).definitions() { for attr in tcx.get_attrs(id, sym::rustc_layout) { match tcx.def_kind(id) { - DefKind::TyAlias { .. } | DefKind::Enum | DefKind::Struct | DefKind::Union => { + DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => { dump_layout_of(tcx, id, attr); } _ => { @@ -57,7 +57,7 @@ pub fn ensure_wf<'tcx>( ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors); + infcx.err_ctxt().report_fulfillment_errors(errors); false } else { // looks WF! diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0aaf85086e455..4590ab9e4f579 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -1,7 +1,7 @@ use Context::*; use rustc_hir as hir; -use rustc_hir::def_id::LocalModDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Destination, Movability, Node}; use rustc_middle::hir::map::Map; @@ -10,19 +10,21 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; -use rustc_span::Span; +use rustc_span::{BytePos, Span}; use crate::errors::{ BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, - UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, + OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, }; #[derive(Clone, Copy, Debug, PartialEq)] enum Context { Normal, + Fn, Loop(hir::LoopSource), Closure(Span), AsyncClosure(Span), + UnlabeledBlock(Span), LabeledBlock, Constant, } @@ -60,6 +62,25 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.with_context(Constant, |v| intravisit::walk_inline_const(v, c)); } + fn visit_fn( + &mut self, + fk: hir::intravisit::FnKind<'hir>, + fd: &'hir hir::FnDecl<'hir>, + b: hir::BodyId, + _: Span, + id: LocalDefId, + ) { + self.with_context(Fn, |v| intravisit::walk_fn(v, fk, fd, b, id)); + } + + fn visit_trait_item(&mut self, trait_item: &'hir hir::TraitItem<'hir>) { + self.with_context(Fn, |v| intravisit::walk_trait_item(v, trait_item)); + } + + fn visit_impl_item(&mut self, impl_item: &'hir hir::ImplItem<'hir>) { + self.with_context(Fn, |v| intravisit::walk_impl_item(v, impl_item)); + } + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { match e.kind { hir::ExprKind::Loop(ref b, _, source, _) => { @@ -83,6 +104,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(&b)); } + hir::ExprKind::Block(ref b, None) if matches!(self.cx, Fn) => { + self.with_context(Normal, |v| v.visit_block(&b)); + } + hir::ExprKind::Block(ref b, None) + if matches!(self.cx, Normal | Constant | UnlabeledBlock(_)) => + { + self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(&b)); + } hir::ExprKind::Break(break_label, ref opt_expr) => { if let Some(e) = opt_expr { self.visit_expr(e); @@ -147,7 +176,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } } - self.require_break_cx("break", e.span); + let sp_lo = e.span.with_lo(e.span.lo() + BytePos("break".len() as u32)); + let label_sp = match break_label.label { + Some(label) => sp_lo.with_hi(label.ident.span.hi()), + None => sp_lo.shrink_to_lo(), + }; + self.require_break_cx("break", e.span, label_sp); } hir::ExprKind::Continue(destination) => { self.require_label_in_labeled_block(e.span, &destination, "continue"); @@ -169,7 +203,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } Err(_) => {} } - self.require_break_cx("continue", e.span) + self.require_break_cx("continue", e.span, e.span) } _ => intravisit::walk_expr(self, e), } @@ -187,7 +221,8 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.cx = old_cx; } - fn require_break_cx(&self, name: &str, span: Span) { + fn require_break_cx(&self, name: &str, span: Span, break_span: Span) { + let is_break = name == "break"; match self.cx { LabeledBlock | Loop(_) => {} Closure(closure_span) => { @@ -196,8 +231,12 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { AsyncClosure(closure_span) => { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } - Normal | Constant => { - self.sess.emit_err(OutsideLoop { span, name, is_break: name == "break" }); + UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => { + let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); + self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion }); + } + Normal | Constant | Fn | UnlabeledBlock(_) => { + self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion: None }); } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 1c2303ae9e069..ab85f680fcf9b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -291,8 +291,7 @@ where | ty::Param(..) | ty::Bound(..) | ty::Error(_) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) => {} + | ty::GeneratorWitness(..) => {} ty::Placeholder(..) | ty::Infer(..) => { bug!("unexpected type: {:?}", ty) } @@ -589,7 +588,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.update(def_id, macro_ev, Level::Reachable); match def_kind { // No type privacy, so can be directly marked as reachable. - DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias { .. } => { + DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -1638,8 +1637,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { let def_kind = tcx.def_kind(def_id); match def_kind { - DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias { .. } => { - if let DefKind::TyAlias { .. } = def_kind { + DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { + if let DefKind::TyAlias = def_kind { self.check_unnameable(def_id, effective_vis); } self.check(def_id, item_visibility, effective_vis).generics().predicates().ty(); diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index a44dd5ede2fd2..a350e8b2e3a43 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } -rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 9a0fcbb37a724..30621a135ebc3 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -92,7 +92,7 @@ where } #[inline(always)] - fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState + fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState where QueryCtxt<'tcx>: 'a, { @@ -145,7 +145,7 @@ where fn value_from_cycle_error( self, tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], + cycle: &[QueryInfo], guar: ErrorGuaranteed, ) -> Self::Value { (self.dynamic.value_from_cycle_error)(tcx, cycle, guar) @@ -198,6 +198,8 @@ trait QueryConfigRestored<'tcx> { type RestoredValue; type Config: QueryConfig>; + const NAME: &'static &'static str; + fn config(tcx: TyCtxt<'tcx>) -> Self::Config; fn restore(value: >>::Value) -> Self::RestoredValue; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f2fdf066d15c9..4516708ce17c9 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -8,7 +8,9 @@ use crate::QueryConfigRestored; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_data_structures::sync::Lock; use rustc_errors::Diagnostic; + use rustc_index::Idx; +use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::{ self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex, }; @@ -53,7 +55,7 @@ impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type DepKind = rustc_middle::dep_graph::DepKind; + type Deps = rustc_middle::dep_graph::DepsType; type DepContext = TyCtxt<'tcx>; #[inline] @@ -78,7 +80,7 @@ impl QueryContext for QueryCtxt<'_> { tls::with_related_context(self.tcx, |icx| icx.query) } - fn try_collect_active_jobs(self) -> Option> { + fn try_collect_active_jobs(self) -> Option { let mut jobs = QueryMap::default(); for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() { @@ -154,7 +156,7 @@ impl QueryContext for QueryCtxt<'_> { let mut span = None; let mut layout_of_depth = None; if let Some(map) = self.try_collect_active_jobs() { - if let Some((info, depth)) = job.try_find_layout_root(map) { + if let Some((info, depth)) = job.try_find_layout_root(map, dep_kinds::layout_of) { span = Some(info.job.span); layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); } @@ -300,7 +302,7 @@ pub(crate) fn create_query_frame< key: K, kind: DepKind, name: &'static str, -) -> QueryStackFrame { +) -> QueryStackFrame { // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!( // Disable visible paths printing for performance reasons. @@ -312,7 +314,7 @@ pub(crate) fn create_query_frame< ); let description = if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description }; - let span = if kind == dep_graph::DepKind::def_span || with_no_queries() { + let span = if kind == dep_graph::dep_kinds::def_span || with_no_queries() { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -320,7 +322,7 @@ pub(crate) fn create_query_frame< Some(key.default_span(tcx)) }; let def_id = key.key_as_def_id(); - let def_kind = if kind == dep_graph::DepKind::opt_def_kind || with_no_queries() { + let def_kind = if kind == dep_graph::dep_kinds::opt_def_kind || with_no_queries() { // Try to avoid infinite recursion. None } else { @@ -329,7 +331,7 @@ pub(crate) fn create_query_frame< let hash = || { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); - std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); + kind.as_usize().hash_stable(&mut hcx, &mut hasher); key.hash_stable(&mut hcx, &mut hasher); hasher.finish::() }) @@ -430,8 +432,8 @@ where // hit the cache instead of having to go through `force_from_dep_node`. // This assertion makes sure, we actually keep applying the solution above. debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" + dep_node.kind != dep_kinds::codegen_unit, + "calling force_from_dep_node() on dep_kinds::codegen_unit" ); if let Some(key) = Q::Key::recover(tcx, &dep_node) { @@ -457,6 +459,7 @@ where fingerprint_style, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: Q::NAME, }; } @@ -470,6 +473,7 @@ where try_load_from_on_disk_cache: Some(|tcx, dep_node| { try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node) }), + name: Q::NAME, } } @@ -565,7 +569,7 @@ macro_rules! define_queries { DynamicQuery { name: stringify!($name), eval_always: is_eval_always!([$($modifiers)*]), - dep_kind: dep_graph::DepKind::$name, + dep_kind: dep_graph::dep_kinds::$name, handle_cycle_error: handle_cycle_error!([$($modifiers)*]), query_state: offset_of!(QueryStates<'tcx> => $name), query_cache: offset_of!(QueryCaches<'tcx> => $name), @@ -636,6 +640,8 @@ macro_rules! define_queries { { feedable!([$($modifiers)*]) }, >; + const NAME: &'static &'static str = &stringify!($name); + #[inline(always)] fn config(tcx: TyCtxt<'tcx>) -> Self::Config { DynamicConfig { @@ -649,9 +655,9 @@ macro_rules! define_queries { } } - pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { + pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { let make_query = |tcx, key| { - let kind = rustc_middle::dep_graph::DepKind::$name; + let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; @@ -709,7 +715,7 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] = + const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] = &[$(query_impl::$name::try_collect_active_jobs),*]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ @@ -737,6 +743,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, + name: &"Null", } } @@ -748,6 +755,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, + name: &"Red", } } @@ -758,6 +766,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"TraitSelect", } } @@ -768,6 +777,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Opaque, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"CompileCodegenUnit", } } @@ -778,6 +788,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Opaque, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"CompileMonoItem", } } diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl index d5fed8fe179fd..d7ab755751118 100644 --- a/compiler/rustc_query_system/messages.ftl +++ b/compiler/rustc_query_system/messages.ftl @@ -15,8 +15,6 @@ query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} query_system_cycle_usage = cycle used when {$usage} -query_system_cycle_which_requires = ...which requires {$desc}... - query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node} .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs index c2c9600f5552c..103a6c01bd274 100644 --- a/compiler/rustc_query_system/src/dep_graph/debug.rs +++ b/compiler/rustc_query_system/src/dep_graph/debug.rs @@ -1,6 +1,6 @@ //! Code for debugging the dep-graph. -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepNode, DepNodeIndex}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use std::error::Error; @@ -28,7 +28,7 @@ impl DepNodeFilter { } /// Tests whether `node` meets the filter, returning true if so. - pub fn test(&self, node: &DepNode) -> bool { + pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{node:?}"); self.text.split('&').map(|s| s.trim()).all(|f| debug_str.contains(f)) } @@ -36,14 +36,14 @@ impl DepNodeFilter { /// A filter like `F -> G` where `F` and `G` are valid dep-node /// filters. This can be used to test the source/target independently. -pub struct EdgeFilter { +pub struct EdgeFilter { pub source: DepNodeFilter, pub target: DepNodeFilter, - pub index_to_node: Lock>>, + pub index_to_node: Lock>, } -impl EdgeFilter { - pub fn new(test: &str) -> Result, Box> { +impl EdgeFilter { + pub fn new(test: &str) -> Result> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into()) @@ -57,7 +57,7 @@ impl EdgeFilter { } #[cfg(debug_assertions)] - pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { + pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 39a4cb1b179b4..17f96896a504b 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -42,36 +42,84 @@ //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. -use super::{DepContext, DepKind, FingerprintStyle}; +use super::{DepContext, FingerprintStyle}; use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; +use rustc_data_structures::AtomicRef; use rustc_hir::definitions::DefPathHash; use std::fmt; use std::hash::Hash; -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct DepNode { - pub kind: K, +/// This serves as an index into arrays built by `make_dep_kind_array`. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DepKind { + variant: u16, +} + +impl DepKind { + #[inline] + pub const fn new(variant: u16) -> Self { + Self { variant } + } + + #[inline] + pub const fn as_inner(&self) -> u16 { + self.variant + } + + #[inline] + pub const fn as_usize(&self) -> usize { + self.variant as usize + } +} + +static_assert_size!(DepKind, 2); + +pub fn default_dep_kind_debug(kind: DepKind, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DepKind").field("variant", &kind.variant).finish() +} + +pub static DEP_KIND_DEBUG: AtomicRef) -> fmt::Result> = + AtomicRef::new(&(default_dep_kind_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + +impl fmt::Debug for DepKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (*DEP_KIND_DEBUG)(*self, f) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DepNode { + pub kind: DepKind, pub hash: PackedFingerprint, } -impl DepNode { +// We keep a lot of `DepNode`s in memory during compilation. It's not +// required that their size stay the same, but we don't want to change +// it inadvertently. This assert just ensures we're aware of any change. +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +static_assert_size!(DepNode, 18); + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +static_assert_size!(DepNode, 24); + +impl DepNode { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - pub fn new_no_params(tcx: Tcx, kind: K) -> DepNode + pub fn new_no_params(tcx: Tcx, kind: DepKind) -> DepNode where - Tcx: super::DepContext, + Tcx: super::DepContext, { debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } - pub fn construct(tcx: Tcx, kind: K, arg: &Key) -> DepNode + pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode where - Tcx: super::DepContext, + Tcx: super::DepContext, Key: DepNodeParams, { let hash = arg.to_fingerprint(tcx); @@ -93,18 +141,25 @@ impl DepNode { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(tcx: Tcx, def_path_hash: DefPathHash, kind: K) -> Self + pub fn from_def_path_hash(tcx: Tcx, def_path_hash: DefPathHash, kind: DepKind) -> Self where - Tcx: super::DepContext, + Tcx: super::DepContext, { debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } } -impl fmt::Debug for DepNode { +pub fn default_dep_node_debug(node: DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DepNode").field("kind", &node.kind).field("hash", &node.hash).finish() +} + +pub static DEP_NODE_DEBUG: AtomicRef) -> fmt::Result> = + AtomicRef::new(&(default_dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + +impl fmt::Debug for DepNode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - K::debug_node(self, f) + (*DEP_NODE_DEBUG)(*self, f) } } @@ -129,7 +184,7 @@ pub trait DepNodeParams: fmt::Debug + Sized { /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. - fn recover(tcx: Tcx, dep_node: &DepNode) -> Option; + fn recover(tcx: Tcx, dep_node: &DepNode) -> Option; } impl DepNodeParams for T @@ -156,7 +211,7 @@ where } #[inline(always)] - default fn recover(_: Tcx, _: &DepNode) -> Option { + default fn recover(_: Tcx, _: &DepNode) -> Option { None } } @@ -216,10 +271,13 @@ pub struct DepKindStruct { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option) -> bool>, + pub force_from_dep_node: Option bool>, /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option)>, + pub try_load_from_on_disk_cache: Option, + + /// The name of this dep kind. + pub name: &'static &'static str, } /// A "work product" corresponds to a `.o` (or other) file that we diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index fa54e1a2e6a74..c7e92d7b2b227 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -17,7 +17,7 @@ use std::sync::atomic::Ordering::Relaxed; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; +use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::EdgesVec; use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffects}; @@ -26,8 +26,8 @@ use crate::query::{QueryContext, QuerySideEffects}; use {super::debug::EdgeFilter, std::env}; #[derive(Clone)] -pub struct DepGraph { - data: Option>>, +pub struct DepGraph { + data: Option>>, /// This field is used for assigning DepNodeIndices when running in /// non-incremental mode. Even in non-incremental mode we make sure that @@ -74,16 +74,16 @@ impl DepNodeColor { } } -pub struct DepGraphData { +pub struct DepGraphData { /// The new encoding of the dependency graph, optimized for red/green /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore, but we do reference shared data to save space. - current: CurrentDepGraph, + current: CurrentDepGraph, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. - previous: SerializedDepGraph, + previous: SerializedDepGraph, colors: DepNodeColorMap, @@ -95,12 +95,12 @@ pub struct DepGraphData { /// this map. We can later look for and extract that data. previous_work_products: WorkProductMap, - dep_node_debug: Lock, String>>, + dep_node_debug: Lock>, /// Used by incremental compilation tests to assert that /// a particular query result was decoded from disk /// (not just marked green) - debug_loaded_from_disk: Lock>>, + debug_loaded_from_disk: Lock>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Fingerprint @@ -112,15 +112,15 @@ where stable_hasher.finish() } -impl DepGraph { +impl DepGraph { pub fn new( profiler: &SelfProfilerRef, - prev_graph: SerializedDepGraph, + prev_graph: SerializedDepGraph, prev_work_products: WorkProductMap, encoder: FileEncoder, record_graph: bool, record_stats: bool, - ) -> DepGraph { + ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); let current = CurrentDepGraph::new( @@ -136,7 +136,7 @@ impl DepGraph { // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( profiler, - DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() }, + DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -146,7 +146,7 @@ impl DepGraph { let (red_node_index, red_node_prev_index_and_color) = current.intern_node( profiler, &prev_graph, - DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() }, + DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), None, false, @@ -181,12 +181,12 @@ impl DepGraph { } } - pub fn new_disabled() -> DepGraph { + pub fn new_disabled() -> DepGraph { DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) } } #[inline] - pub fn data(&self) -> Option<&DepGraphData> { + pub fn data(&self) -> Option<&DepGraphData> { self.data.as_deref() } @@ -196,7 +196,7 @@ impl DepGraph { self.data.is_some() } - pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { if let Some(data) = &self.data { data.current.encoder.borrow().with_query(f) } @@ -204,7 +204,7 @@ impl DepGraph { pub fn assert_ignored(&self) { if let Some(..) = self.data { - K::read_deps(|task_deps| { + D::read_deps(|task_deps| { assert_matches!( task_deps, TaskDepsRef::Ignore, @@ -218,7 +218,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Ignore, op) + D::with_deps(TaskDepsRef::Ignore, op) } /// Used to wrap the deserialization of a query result from disk, @@ -271,13 +271,13 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Forbid, op) + D::with_deps(TaskDepsRef::Forbid, op) } #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, - key: DepNode, + key: DepNode, cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, @@ -289,10 +289,10 @@ impl DepGraph { } } - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, cx: Tcx, - dep_kind: K, + dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) where @@ -305,7 +305,7 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { /// Starts a new dep-graph task. Dep-graph tasks are specified /// using a free function (`task`) and **not** a closure -- this /// is intentional because we want to exercise tight control over @@ -334,9 +334,9 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, - key: DepNode, + key: DepNode, cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, @@ -354,7 +354,7 @@ impl DepGraphData { - dep-node: {key:?}" ); - let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg)); + let with_deps = |task_deps| D::with_deps(task_deps, || task(cx, arg)); let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { (with_deps(TaskDepsRef::EvalAlways), EdgesVec::new()) } else { @@ -402,10 +402,10 @@ impl DepGraphData { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, cx: Tcx, - dep_kind: K, + dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) where @@ -414,7 +414,7 @@ impl DepGraphData { debug_assert!(!cx.is_eval_always(dep_kind)); let task_deps = Lock::new(TaskDeps::default()); - let result = K::with_deps(TaskDepsRef::Allow(&task_deps), op); + let result = D::with_deps(TaskDepsRef::Allow(&task_deps), op); let task_deps = task_deps.into_inner(); let task_deps = task_deps.reads; @@ -461,11 +461,11 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { #[inline] pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { - K::read_deps(|task_deps| { + D::read_deps(|task_deps| { let mut task_deps = match task_deps { TaskDepsRef::Allow(deps) => deps.lock(), TaskDepsRef::EvalAlways => { @@ -532,9 +532,9 @@ impl DepGraph { /// FIXME: If the code is changed enough for this node to be marked before requiring the /// caller's node, we suppose that those changes will be enough to mark this node red and /// force a recomputation using the "normal" way. - pub fn with_feed_task, A: Debug, R: Debug>( + pub fn with_feed_task, A: Debug, R: Debug>( &self, - node: DepNode, + node: DepNode, cx: Ctxt, key: A, result: &R, @@ -573,7 +573,7 @@ impl DepGraph { } let mut edges = EdgesVec::new(); - K::read_deps(|task_deps| match task_deps { + D::read_deps(|task_deps| match task_deps { TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()), TaskDepsRef::EvalAlways => { edges.push(DepNodeIndex::FOREVER_RED_NODE); @@ -623,9 +623,9 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { #[inline] - pub fn dep_node_index_of_opt(&self, dep_node: &DepNode) -> Option { + pub fn dep_node_index_of_opt(&self, dep_node: &DepNode) -> Option { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { self.current.prev_index_to_index.lock()[prev_index] } else { @@ -634,11 +634,11 @@ impl DepGraphData { } #[inline] - pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { + pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { self.dep_node_index_of_opt(dep_node).is_some() } - fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { self.colors.get(prev_index) } else { @@ -660,18 +660,18 @@ impl DepGraphData { } #[inline] - pub fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { + pub fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { self.previous.index_to_node(prev_index) } - pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { + pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } } -impl DepGraph { +impl DepGraph { #[inline] - pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { + pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node)) } @@ -687,12 +687,12 @@ impl DepGraph { &self.data.as_ref().unwrap().previous_work_products } - pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { + pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { self.data.as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node) } #[inline(always)] - pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) + pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) where F: FnOnce() -> String, { @@ -705,11 +705,11 @@ impl DepGraph { dep_node_debug.borrow_mut().insert(dep_node, debug_str); } - pub fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { + pub fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { self.data.as_ref()?.dep_node_debug.borrow().get(&dep_node).cloned() } - fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(ref data) = self.data { return data.node_color(dep_node); } @@ -717,25 +717,25 @@ impl DepGraph { None } - pub fn try_mark_green>( + pub fn try_mark_green>( &self, qcx: Qcx, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { self.data().and_then(|data| data.try_mark_green(qcx, dep_node)) } } -impl DepGraphData { +impl DepGraphData { /// Try to mark a node index for the node dep_node. /// /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green>( + pub fn try_mark_green>( &self, qcx: Qcx, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); @@ -757,11 +757,11 @@ impl DepGraphData { } #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, + dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); @@ -845,11 +845,11 @@ impl DepGraphData { /// Try to mark a dep-node which existed in the previous compilation session as green. #[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")] - fn try_mark_previous_green>( + fn try_mark_previous_green>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, + dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option { let frame = MarkFrame { index: prev_dep_node_index, parent: frame }; @@ -916,7 +916,7 @@ impl DepGraphData { /// This may be called concurrently on multiple threads for the same dep node. #[cold] #[inline(never)] - fn emit_side_effects>( + fn emit_side_effects>( &self, qcx: Qcx, dep_node_index: DepNodeIndex, @@ -940,16 +940,16 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { /// Returns true if the given node has been marked as red during the /// current compilation session. Used in various assertions - pub fn is_red(&self, dep_node: &DepNode) -> bool { + pub fn is_red(&self, dep_node: &DepNode) -> bool { self.node_color(dep_node) == Some(DepNodeColor::Red) } /// Returns true if the given node has been marked as green during the /// current compilation session. Used in various assertions - pub fn is_green(&self, dep_node: &DepNode) -> bool { + pub fn is_green(&self, dep_node: &DepNode) -> bool { self.node_color(dep_node).is_some_and(|c| c.is_green()) } @@ -961,7 +961,7 @@ impl DepGraph { /// /// This method will only load queries that will end up in the disk cache. /// Other queries will not be executed. - pub fn exec_cache_promotions>(&self, tcx: Tcx) { + pub fn exec_cache_promotions(&self, tcx: Tcx) { let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); @@ -1076,9 +1076,9 @@ rustc_index::newtype_index! { /// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When /// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index` /// first, and `data` second. -pub(super) struct CurrentDepGraph { - encoder: Steal>, - new_node_to_index: Sharded, DepNodeIndex>>, +pub(super) struct CurrentDepGraph { + encoder: Steal>, + new_node_to_index: Sharded>, prev_index_to_index: Lock>>, /// This is used to verify that fingerprints do not change between the creation of a node @@ -1089,7 +1089,7 @@ pub(super) struct CurrentDepGraph { /// Used to trap when a specific edge is added to the graph. /// This is used for debug purposes and is only active with `debug_assertions`. #[cfg(debug_assertions)] - forbidden_edge: Option>, + forbidden_edge: Option, /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of /// their edges. This has the beneficial side-effect that multiple anonymous @@ -1116,14 +1116,14 @@ pub(super) struct CurrentDepGraph { node_intern_event_id: Option, } -impl CurrentDepGraph { +impl CurrentDepGraph { fn new( profiler: &SelfProfilerRef, prev_graph_node_count: usize, encoder: FileEncoder, record_graph: bool, record_stats: bool, - ) -> CurrentDepGraph { + ) -> Self { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -1178,7 +1178,7 @@ impl CurrentDepGraph { } #[cfg(debug_assertions)] - fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode, fingerprint: Fingerprint) { + fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode, fingerprint: Fingerprint) { if let Some(forbidden_edge) = &self.forbidden_edge { forbidden_edge.index_to_node.lock().insert(dep_node_index, key); } @@ -1192,7 +1192,7 @@ impl CurrentDepGraph { fn intern_new_node( &self, profiler: &SelfProfilerRef, - key: DepNode, + key: DepNode, edges: EdgesVec, current_fingerprint: Fingerprint, ) -> DepNodeIndex { @@ -1215,8 +1215,8 @@ impl CurrentDepGraph { fn intern_node( &self, profiler: &SelfProfilerRef, - prev_graph: &SerializedDepGraph, - key: DepNode, + prev_graph: &SerializedDepGraph, + key: DepNode, edges: EdgesVec, fingerprint: Option, print_status: bool, @@ -1289,7 +1289,7 @@ impl CurrentDepGraph { fn promote_node_and_deps_to_current( &self, profiler: &SelfProfilerRef, - prev_graph: &SerializedDepGraph, + prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) -> DepNodeIndex { self.debug_assert_not_in_new_nodes(prev_graph, prev_index); @@ -1317,7 +1317,7 @@ impl CurrentDepGraph { #[inline] fn debug_assert_not_in_new_nodes( &self, - prev_graph: &SerializedDepGraph, + prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) { let node = &prev_graph.index_to_node(prev_index); @@ -1329,11 +1329,11 @@ impl CurrentDepGraph { } #[derive(Debug, Clone, Copy)] -pub enum TaskDepsRef<'a, K: DepKind> { +pub enum TaskDepsRef<'a> { /// New dependencies can be added to the /// `TaskDeps`. This is used when executing a 'normal' query /// (no `eval_always` modifier) - Allow(&'a Lock>), + Allow(&'a Lock), /// This is used when executing an `eval_always` query. We don't /// need to track dependencies for a query that's always /// re-executed -- but we need to know that this is an `eval_always` @@ -1350,15 +1350,15 @@ pub enum TaskDepsRef<'a, K: DepKind> { } #[derive(Debug)] -pub struct TaskDeps { +pub struct TaskDeps { #[cfg(debug_assertions)] - node: Option>, + node: Option, reads: EdgesVec, read_set: FxHashSet, - phantom_data: PhantomData>, + phantom_data: PhantomData, } -impl Default for TaskDeps { +impl Default for TaskDeps { fn default() -> Self { Self { #[cfg(debug_assertions)] @@ -1410,10 +1410,7 @@ impl DepNodeColorMap { #[inline(never)] #[cold] -pub(crate) fn print_markframe_trace( - graph: &DepGraph, - frame: Option<&MarkFrame<'_>>, -) { +pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: Option<&MarkFrame<'_>>) { let data = graph.data.as_ref().unwrap(); eprintln!("there was a panic while trying to force a dep node"); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 272028d35bf7e..624ae680a8ff7 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -1,11 +1,11 @@ pub mod debug; -mod dep_node; +pub mod dep_node; mod edges; mod graph; mod query; mod serialized; -pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId}; +pub use dep_node::{DepKind, DepKindStruct, DepNode, DepNodeParams, WorkProductId}; pub use edges::EdgesVec; pub use graph::{ hash_result, DepGraph, DepGraphData, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, @@ -16,22 +16,20 @@ pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; -use std::hash::Hash; -use std::{fmt, panic}; +use std::panic; use self::graph::{print_markframe_trace, MarkFrame}; pub trait DepContext: Copy { - type DepKind: self::DepKind; + type Deps: Deps; /// Create a hashing context for hashing new results. fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; /// Access the DepGraph. - fn dep_graph(&self) -> &DepGraph; + fn dep_graph(&self) -> &DepGraph; /// Access the profiler. fn profiler(&self) -> &SelfProfilerRef; @@ -39,10 +37,10 @@ pub trait DepContext: Copy { /// Access the compiler session. fn sess(&self) -> &Session; - fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct; + fn dep_kind_info(&self, dep_node: DepKind) -> &DepKindStruct; #[inline(always)] - fn fingerprint_style(self, kind: Self::DepKind) -> FingerprintStyle { + fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { let data = self.dep_kind_info(kind); if data.is_anon { return FingerprintStyle::Opaque; @@ -52,18 +50,14 @@ pub trait DepContext: Copy { #[inline(always)] /// Return whether this kind always require evaluation. - fn is_eval_always(self, kind: Self::DepKind) -> bool { + fn is_eval_always(self, kind: DepKind) -> bool { self.dep_kind_info(kind).is_eval_always } /// Try to force a dep node to execute and see if it's green. #[inline] #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node( - self, - dep_node: DepNode, - frame: Option<&MarkFrame<'_>>, - ) -> bool { + fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| { @@ -81,7 +75,7 @@ pub trait DepContext: Copy { } /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(self, dep_node: DepNode) { + fn try_load_from_on_disk_cache(self, dep_node: DepNode) { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.try_load_from_on_disk_cache { f(self, dep_node) @@ -89,15 +83,37 @@ pub trait DepContext: Copy { } } +pub trait Deps { + /// Execute the operation with provided dependencies. + fn with_deps(deps: TaskDepsRef<'_>, op: OP) -> R + where + OP: FnOnce() -> R; + + /// Access dependencies from current implicit context. + fn read_deps(op: OP) + where + OP: for<'a> FnOnce(TaskDepsRef<'a>); + + /// We use this for most things when incr. comp. is turned off. + const DEP_KIND_NULL: DepKind; + + /// We use this to create a forever-red node. + const DEP_KIND_RED: DepKind; + + /// This is the highest value a `DepKind` can have. It's used during encoding to + /// pack information into the unused bits. + const DEP_KIND_MAX: u16; +} + pub trait HasDepContext: Copy { - type DepKind: self::DepKind; - type DepContext: self::DepContext; + type Deps: self::Deps; + type DepContext: self::DepContext; fn dep_context(&self) -> &Self::DepContext; } impl HasDepContext for T { - type DepKind = T::DepKind; + type Deps = T::Deps; type DepContext = Self; fn dep_context(&self) -> &Self::DepContext { @@ -106,7 +122,7 @@ impl HasDepContext for T { } impl HasDepContext for (T, Q) { - type DepKind = T::DepKind; + type Deps = T::Deps; type DepContext = T::DepContext; fn dep_context(&self) -> &Self::DepContext { @@ -138,31 +154,3 @@ impl FingerprintStyle { } } } - -/// Describe the different families of dependency nodes. -pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { - /// DepKind to use when incr. comp. is turned off. - const NULL: Self; - - /// DepKind to use to create the initial forever-red node. - const RED: Self; - - /// Implementation of `std::fmt::Debug` for `DepNode`. - fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; - - /// Execute the operation with provided dependencies. - fn with_deps(deps: TaskDepsRef<'_, Self>, op: OP) -> R - where - OP: FnOnce() -> R; - - /// Access dependencies from current implicit context. - fn read_deps(op: OP) - where - OP: for<'a> FnOnce(TaskDepsRef<'a, Self>); - - fn from_u16(u: u16) -> Self; - - fn to_u16(self) -> u16; - - const MAX: u16; -} diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs index 5cbc6bf8f8af3..5969e5fbe98f4 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_query_system/src/dep_graph/query.rs @@ -2,16 +2,16 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::implementation::{Direction, Graph, NodeIndex, INCOMING}; use rustc_index::IndexVec; -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepNode, DepNodeIndex}; -pub struct DepGraphQuery { - pub graph: Graph, ()>, - pub indices: FxHashMap, NodeIndex>, +pub struct DepGraphQuery { + pub graph: Graph, + pub indices: FxHashMap, pub dep_index_to_index: IndexVec>, } -impl DepGraphQuery { - pub fn new(prev_node_count: usize) -> DepGraphQuery { +impl DepGraphQuery { + pub fn new(prev_node_count: usize) -> DepGraphQuery { let node_count = prev_node_count + prev_node_count / 4; let edge_count = 6 * node_count; @@ -22,7 +22,7 @@ impl DepGraphQuery { DepGraphQuery { graph, indices, dep_index_to_index } } - pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { + pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { let source = self.graph.add_node(node); self.dep_index_to_index.insert(index, source); self.indices.insert(node, source); @@ -37,11 +37,11 @@ impl DepGraphQuery { } } - pub fn nodes(&self) -> Vec<&DepNode> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes().iter().map(|n| &n.data).collect() } - pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { self.graph .all_edges() .iter() @@ -50,7 +50,7 @@ impl DepGraphQuery { .collect() } - fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction).map(|s| self.graph.node_data(s)).collect() } else { @@ -59,7 +59,7 @@ impl DepGraphQuery { } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 07eb10cba02c6..fcf46be6e6f5a 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -36,7 +36,7 @@ //! store it directly after the header with leb128. use super::query::DepGraphQuery; -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepKind, DepNode, DepNodeIndex, Deps}; use crate::dep_graph::EdgesVec; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::PackedFingerprint; @@ -70,9 +70,9 @@ const DEP_NODE_WIDTH_BITS: usize = DEP_NODE_SIZE / 2; /// Data for use when recompiling the **current crate**. #[derive(Debug)] -pub struct SerializedDepGraph { +pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - nodes: IndexVec>, + nodes: IndexVec, /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to /// the DepNode at the same index in the nodes vector. fingerprints: IndexVec, @@ -88,7 +88,7 @@ pub struct SerializedDepGraph { index: Vec>, } -impl Default for SerializedDepGraph { +impl Default for SerializedDepGraph { fn default() -> Self { SerializedDepGraph { nodes: Default::default(), @@ -100,7 +100,7 @@ impl Default for SerializedDepGraph { } } -impl SerializedDepGraph { +impl SerializedDepGraph { #[inline] pub fn edge_targets_from( &self, @@ -134,13 +134,13 @@ impl SerializedDepGraph { } #[inline] - pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { self.nodes[dep_node_index] } #[inline] - pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { - self.index.get(dep_node.kind.to_u16() as usize)?.get(&dep_node.hash).cloned() + pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { + self.index.get(dep_node.kind.as_usize())?.get(&dep_node.hash).cloned() } #[inline] @@ -184,11 +184,9 @@ fn mask(bits: usize) -> usize { usize::MAX >> ((std::mem::size_of::() * 8) - bits) } -impl<'a, K: DepKind + Decodable>> Decodable> - for SerializedDepGraph -{ +impl SerializedDepGraph { #[instrument(level = "debug", skip(d))] - fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { + pub fn decode(d: &mut MemDecoder<'_>) -> SerializedDepGraph { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); let (node_count, edge_count) = @@ -217,14 +215,14 @@ impl<'a, K: DepKind + Decodable>> Decodable> // least (34 byte header + 1 byte len + 64 bytes edge data), which is ~1%. A 2-byte leb128 // length is about the same fractional overhead and it amortizes for yet greater lengths. let mut edge_list_data = Vec::with_capacity( - graph_bytes - node_count * std::mem::size_of::>(), + graph_bytes - node_count * std::mem::size_of::>(), ); for _index in 0..node_count { // Decode the header for this edge; the header packs together as many of the fixed-size // fields as possible to limit the number of times we update decoder state. let node_header = - SerializedNodeHeader:: { bytes: d.read_array(), _marker: PhantomData }; + SerializedNodeHeader:: { bytes: d.read_array(), _marker: PhantomData }; let _i: SerializedDepNodeIndex = nodes.push(node_header.node()); debug_assert_eq!(_i.index(), _index); @@ -256,12 +254,12 @@ impl<'a, K: DepKind + Decodable>> Decodable> edge_list_data.extend(&[0u8; DEP_NODE_PAD]); // Read the number of each dep kind and use it to create an hash map with a suitable size. - let mut index: Vec<_> = (0..(K::MAX as usize + 1)) + let mut index: Vec<_> = (0..(D::DEP_KIND_MAX + 1)) .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); for (idx, node) in nodes.iter_enumerated() { - index[node.kind.to_u16() as usize].insert(node.hash, idx); + index[node.kind.as_usize()].insert(node.hash, idx); } SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index } @@ -276,20 +274,20 @@ impl<'a, K: DepKind + Decodable>> Decodable> /// * The `DepKind`'s discriminant (a u16, but not all bits are used...) /// * The byte width of the encoded edges for this node /// * In whatever bits remain, the length of the edge list for this node, if it fits -struct SerializedNodeHeader { +struct SerializedNodeHeader { // 2 bytes for the DepNode // 16 for Fingerprint in DepNode // 16 for Fingerprint in NodeInfo bytes: [u8; 34], - _marker: PhantomData, + _marker: PhantomData, } // The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only // to make the implementation of `SerializedNodeHeader` simpler. -struct Unpacked { +struct Unpacked { len: Option, bytes_per_index: usize, - kind: K, + kind: DepKind, hash: PackedFingerprint, fingerprint: Fingerprint, } @@ -301,20 +299,20 @@ struct Unpacked { // 0..M length of the edge // M..M+N bytes per index // M+N..16 kind -impl SerializedNodeHeader { - const TOTAL_BITS: usize = std::mem::size_of::() * 8; +impl SerializedNodeHeader { + const TOTAL_BITS: usize = std::mem::size_of::() * 8; const LEN_BITS: usize = Self::TOTAL_BITS - Self::KIND_BITS - Self::WIDTH_BITS; const WIDTH_BITS: usize = DEP_NODE_WIDTH_BITS; - const KIND_BITS: usize = Self::TOTAL_BITS - K::MAX.leading_zeros() as usize; + const KIND_BITS: usize = Self::TOTAL_BITS - D::DEP_KIND_MAX.leading_zeros() as usize; const MAX_INLINE_LEN: usize = (u16::MAX as usize >> (Self::TOTAL_BITS - Self::LEN_BITS)) - 1; #[inline] - fn new(node_info: &NodeInfo) -> Self { + fn new(node_info: &NodeInfo) -> Self { debug_assert_eq!(Self::TOTAL_BITS, Self::LEN_BITS + Self::WIDTH_BITS + Self::KIND_BITS); let NodeInfo { node, fingerprint, edges } = node_info; - let mut head = node.kind.to_u16(); + let mut head = node.kind.as_inner(); let free_bytes = edges.max_index().leading_zeros() as usize / 8; let bytes_per_index = (DEP_NODE_SIZE - free_bytes).saturating_sub(1); @@ -347,7 +345,7 @@ impl SerializedNodeHeader { } #[inline] - fn unpack(&self) -> Unpacked { + fn unpack(&self) -> Unpacked { let head = u16::from_le_bytes(self.bytes[..2].try_into().unwrap()); let hash = self.bytes[2..18].try_into().unwrap(); let fingerprint = self.bytes[18..].try_into().unwrap(); @@ -359,7 +357,7 @@ impl SerializedNodeHeader { Unpacked { len: len.checked_sub(1), bytes_per_index: bytes_per_index as usize + 1, - kind: DepKind::from_u16(kind), + kind: DepKind::new(kind), hash: Fingerprint::from_le_bytes(hash).into(), fingerprint: Fingerprint::from_le_bytes(fingerprint), } @@ -381,7 +379,7 @@ impl SerializedNodeHeader { } #[inline] - fn node(&self) -> DepNode { + fn node(&self) -> DepNode { let Unpacked { kind, hash, .. } = self.unpack(); DepNode { kind, hash } } @@ -395,15 +393,15 @@ impl SerializedNodeHeader { } #[derive(Debug)] -struct NodeInfo { - node: DepNode, +struct NodeInfo { + node: DepNode, fingerprint: Fingerprint, edges: EdgesVec, } -impl Encodable for NodeInfo { - fn encode(&self, e: &mut FileEncoder) { - let header = SerializedNodeHeader::new(self); +impl NodeInfo { + fn encode(&self, e: &mut FileEncoder) { + let header = SerializedNodeHeader::::new(self); e.write_array(header.bytes); if header.len().is_none() { @@ -420,41 +418,43 @@ impl Encodable for NodeInfo { } } -struct Stat { - kind: K, +struct Stat { + kind: DepKind, node_counter: u64, edge_counter: u64, } -struct EncoderState { +struct EncoderState { encoder: FileEncoder, total_node_count: usize, total_edge_count: usize, - stats: Option>>, + stats: Option>, /// Stores the number of times we've encoded each dep kind. kind_stats: Vec, + marker: PhantomData, } -impl EncoderState { +impl EncoderState { fn new(encoder: FileEncoder, record_stats: bool) -> Self { Self { encoder, total_edge_count: 0, total_node_count: 0, stats: record_stats.then(FxHashMap::default), - kind_stats: iter::repeat(0).take(K::MAX as usize + 1).collect(), + kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(), + marker: PhantomData, } } fn encode_node( &mut self, - node: &NodeInfo, - record_graph: &Option>>, + node: &NodeInfo, + record_graph: &Option>, ) -> DepNodeIndex { let index = DepNodeIndex::new(self.total_node_count); self.total_node_count += 1; - self.kind_stats[node.node.kind.to_u16() as usize] += 1; + self.kind_stats[node.node.kind.as_usize()] += 1; let edge_count = node.edges.len(); self.total_edge_count += edge_count; @@ -475,12 +475,19 @@ impl EncoderState { } let encoder = &mut self.encoder; - node.encode(encoder); + node.encode::(encoder); index } fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { - let Self { mut encoder, total_node_count, total_edge_count, stats: _, kind_stats } = self; + let Self { + mut encoder, + total_node_count, + total_edge_count, + stats: _, + kind_stats, + marker: _, + } = self; let node_count = total_node_count.try_into().unwrap(); let edge_count = total_edge_count.try_into().unwrap(); @@ -506,12 +513,12 @@ impl EncoderState { } } -pub struct GraphEncoder { - status: Lock>, - record_graph: Option>>, +pub struct GraphEncoder { + status: Lock>, + record_graph: Option>, } -impl> GraphEncoder { +impl GraphEncoder { pub fn new( encoder: FileEncoder, prev_node_count: usize, @@ -523,7 +530,7 @@ impl> GraphEncoder { GraphEncoder { status, record_graph } } - pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { if let Some(record_graph) = &self.record_graph { f(&record_graph.lock()) } @@ -584,7 +591,7 @@ impl> GraphEncoder { pub(crate) fn send( &self, profiler: &SelfProfilerRef, - node: DepNode, + node: DepNode, fingerprint: Fingerprint, edges: EdgesVec, ) -> DepNodeIndex { diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d14c6315dc10d..c025fac2631a8 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -1,6 +1,6 @@ //! Query configuration and description traits. -use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; @@ -27,7 +27,7 @@ pub trait QueryConfig: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState + fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState where Qcx: 'a; @@ -57,7 +57,7 @@ pub trait QueryConfig: Copy { fn value_from_cycle_error( self, tcx: Qcx::DepContext, - cycle: &[QueryInfo], + cycle: &[QueryInfo], guar: ErrorGuaranteed, ) -> Self::Value; @@ -66,12 +66,12 @@ pub trait QueryConfig: Copy { fn depth_limit(self) -> bool; fn feedable(self) -> bool; - fn dep_kind(self) -> Qcx::DepKind; + fn dep_kind(self) -> DepKind; fn handle_cycle_error(self) -> HandleCycleError; fn hash_result(self) -> HashResult; // Just here for convenience and checking that the key matches the kind, don't override this. - fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { + fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 6c01dc3c00d40..f2c1f84fccc1d 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,9 +1,8 @@ -use crate::dep_graph::DepKind; +use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; +use crate::query::DepKind; use crate::query::{QueryContext, QueryStackFrame}; -use core::marker::PhantomData; - use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, Level, @@ -30,48 +29,48 @@ use { /// Represents a span and a query key. #[derive(Clone, Debug)] -pub struct QueryInfo { +pub struct QueryInfo { /// The span corresponding to the reason for which this query was required. pub span: Span, - pub query: QueryStackFrame, + pub query: QueryStackFrame, } -pub type QueryMap = FxHashMap>; +pub type QueryMap = FxHashMap; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryJobId(pub NonZeroU64); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query(self, map: &QueryMap) -> QueryStackFrame { map.get(&self).unwrap().query.clone() } #[cfg(parallel_compiler)] - fn span(self, map: &QueryMap) -> Span { + fn span(self, map: &QueryMap) -> Span { map.get(&self).unwrap().job.span } #[cfg(parallel_compiler)] - fn parent(self, map: &QueryMap) -> Option { + fn parent(self, map: &QueryMap) -> Option { map.get(&self).unwrap().job.parent } #[cfg(parallel_compiler)] - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { + fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo { + pub query: QueryStackFrame, + pub job: QueryJob, } /// Represents an active query job. #[derive(Clone)] -pub struct QueryJob { +pub struct QueryJob { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -82,11 +81,10 @@ pub struct QueryJob { /// The latch that is used to wait on this job. #[cfg(parallel_compiler)] - latch: Option>, - spooky: core::marker::PhantomData, + latch: Option, } -impl QueryJob { +impl QueryJob { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { @@ -96,12 +94,11 @@ impl QueryJob { parent, #[cfg(parallel_compiler)] latch: None, - spooky: PhantomData, } } #[cfg(parallel_compiler)] - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -124,12 +121,12 @@ impl QueryJob { } impl QueryJobId { - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack( &self, - query_map: QueryMap, + query_map: QueryMap, current_job: &Option, span: Span, - ) -> CycleError { + ) -> CycleError { // Find the waitee amongst `current_job` parents let mut cycle = Vec::new(); let mut current_job = Option::clone(current_job); @@ -163,18 +160,18 @@ impl QueryJobId { #[cold] #[inline(never)] - pub fn try_find_layout_root( + pub fn try_find_layout_root( &self, - query_map: QueryMap, - ) -> Option<(QueryJobInfo, usize)> { + query_map: QueryMap, + layout_of_kind: DepKind, + ) -> Option<(QueryJobInfo, usize)> { let mut last_layout = None; let mut current_id = Some(*self); let mut depth = 0; while let Some(id) = current_id { let info = query_map.get(&id).unwrap(); - // FIXME: This string comparison should probably not be done. - if format!("{:?}", info.query.dep_kind) == "layout_of" { + if info.query.dep_kind == layout_of_kind { depth += 1; last_layout = Some((info.clone(), depth)); } @@ -185,15 +182,15 @@ impl QueryJobId { } #[cfg(parallel_compiler)] -struct QueryWaiter { +struct QueryWaiter { query: Option, condvar: Condvar, span: Span, - cycle: Mutex>>, + cycle: Mutex>, } #[cfg(parallel_compiler)] -impl QueryWaiter { +impl QueryWaiter { fn notify(&self, registry: &rayon_core::Registry) { rayon_core::mark_unblocked(registry); self.condvar.notify_one(); @@ -201,19 +198,19 @@ impl QueryWaiter { } #[cfg(parallel_compiler)] -struct QueryLatchInfo { +struct QueryLatchInfo { complete: bool, - waiters: Vec>>, + waiters: Vec>, } #[cfg(parallel_compiler)] #[derive(Clone)] -pub(super) struct QueryLatch { - info: Arc>>, +pub(super) struct QueryLatch { + info: Arc>, } #[cfg(parallel_compiler)] -impl QueryLatch { +impl QueryLatch { fn new() -> Self { QueryLatch { info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -221,11 +218,7 @@ impl QueryLatch { } /// Awaits for the query job to complete. - pub(super) fn wait_on( - &self, - query: Option, - span: Span, - ) -> Result<(), CycleError> { + pub(super) fn wait_on(&self, query: Option, span: Span) -> Result<(), CycleError> { let waiter = Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); self.wait_on_inner(&waiter); @@ -240,7 +233,7 @@ impl QueryLatch { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, waiter: &Arc>) { + fn wait_on_inner(&self, waiter: &Arc) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -274,7 +267,7 @@ impl QueryLatch { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc> { + fn extract_waiter(&self, waiter: usize) -> Arc { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -296,14 +289,9 @@ type Waiter = (QueryJobId, usize); /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. #[cfg(parallel_compiler)] -fn visit_waiters( - query_map: &QueryMap, - query: QueryJobId, - mut visit: F, -) -> Option> +fn visit_waiters(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option> where F: FnMut(Span, QueryJobId) -> Option>, - D: DepKind, { // Visit the parent query which is a non-resumable waiter since it's on the same stack if let Some(parent) = query.parent(query_map) { @@ -332,8 +320,8 @@ where /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. #[cfg(parallel_compiler)] -fn cycle_check( - query_map: &QueryMap, +fn cycle_check( + query_map: &QueryMap, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -373,8 +361,8 @@ fn cycle_check( /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. #[cfg(parallel_compiler)] -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root( + query_map: &QueryMap, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -396,10 +384,9 @@ fn connected_to_root( // Deterministically pick an query from a list #[cfg(parallel_compiler)] -fn pick_query<'a, T, F, D>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), - D: DepKind, { // Deterministically pick an entry point // FIXME: Sort this instead @@ -423,10 +410,10 @@ where /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. #[cfg(parallel_compiler)] -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle( + query_map: &QueryMap, jobs: &mut Vec, - wakelist: &mut Vec>>, + wakelist: &mut Vec>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -528,7 +515,7 @@ fn remove_cycle( /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. #[cfg(parallel_compiler)] -pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { +pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { let on_panic = defer(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); @@ -566,9 +553,9 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Regis #[inline(never)] #[cold] -pub(crate) fn report_cycle<'a, D: DepKind>( +pub(crate) fn report_cycle<'a>( sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, + CycleError { usage, cycle: stack }: &CycleError, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { assert!(!stack.is_empty()); @@ -593,9 +580,7 @@ pub(crate) fn report_cycle<'a, D: DepKind>( }); } - let alias = if stack - .iter() - .all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias { .. }))) + let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias))) { Some(crate::error::Alias::Ty) } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) { @@ -655,8 +640,10 @@ pub fn print_query_stack( if let Some(ref mut file) = file { let _ = writeln!( file, - "#{} [{:?}] {}", - count_total, query_info.query.dep_kind, query_info.query.description + "#{} [{}] {}", + count_total, + qcx.dep_context().dep_kind_info(query_info.query.dep_kind).name, + query_info.query.description ); } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index f7619d75be768..05dee9f12dbdb 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -28,27 +28,27 @@ use thin_vec::ThinVec; /// /// This is mostly used in case of cycles for error reporting. #[derive(Clone, Debug)] -pub struct QueryStackFrame { +pub struct QueryStackFrame { pub description: String, span: Option, pub def_id: Option, pub def_kind: Option, pub ty_adt_id: Option, - pub dep_kind: D, + pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. #[cfg(parallel_compiler)] hash: Hash64, } -impl QueryStackFrame { +impl QueryStackFrame { #[inline] pub fn new( description: String, span: Option, def_id: Option, def_kind: Option, - dep_kind: D, + dep_kind: DepKind, ty_adt_id: Option, _hash: impl FnOnce() -> Hash64, ) -> Self { @@ -106,7 +106,7 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn try_collect_active_jobs(self) -> Option>; + fn try_collect_active_jobs(self) -> Option; /// Load side effects associated to the node in the previous session. fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 07db15e6d8be0..ae8414ebba6d7 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,8 +2,8 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; -use crate::dep_graph::{DepGraphData, HasDepContext}; +use crate::dep_graph::DepGraphData; +use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; #[cfg(parallel_compiler)] @@ -18,7 +18,7 @@ use rustc_data_structures::sharded::Sharded; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lock; #[cfg(parallel_compiler)] -use rustc_data_structures::{cold_path, sync}; +use rustc_data_structures::{outline, sync}; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError}; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; @@ -30,24 +30,23 @@ use thin_vec::ThinVec; use super::QueryConfig; -pub struct QueryState { - active: Sharded>>, +pub struct QueryState { + active: Sharded>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryState +impl QueryState where K: Eq + Hash + Copy + Debug, - D: DepKind, { pub fn all_inactive(&self) -> bool { self.active.lock_shards().all(|shard| shard.is_empty()) @@ -56,8 +55,8 @@ where pub fn try_collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame, + jobs: &mut QueryMap, ) -> Option<()> { let mut active = Vec::new(); @@ -82,25 +81,25 @@ where } } -impl Default for QueryState { - fn default() -> QueryState { +impl Default for QueryState { + fn default() -> QueryState { QueryState { active: Default::default() } } } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K, D: DepKind> +struct JobOwner<'tcx, K> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'tcx QueryState, key: K, } #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value where Q: QueryConfig, Qcx: QueryContext, @@ -112,7 +111,7 @@ where fn handle_cycle_error( query: Q, qcx: Qcx, - cycle_error: &CycleError, + cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, ) -> Q::Value where @@ -137,7 +136,7 @@ where } } -impl<'tcx, K, D: DepKind> JobOwner<'tcx, K, D> +impl<'tcx, K> JobOwner<'tcx, K> where K: Eq + Hash + Copy, { @@ -169,10 +168,9 @@ where } } -impl<'tcx, K, D> Drop for JobOwner<'tcx, K, D> +impl<'tcx, K> Drop for JobOwner<'tcx, K> where K: Eq + Hash + Copy, - D: DepKind, { #[inline(never)] #[cold] @@ -195,10 +193,10 @@ where } #[derive(Clone)] -pub(crate) struct CycleError { +pub(crate) struct CycleError { /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec>, + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec, } /// Checks if the query is already computed and in the cache. @@ -248,7 +246,7 @@ fn wait_for_query( qcx: Qcx, span: Span, key: Q::Key, - latch: QueryLatch, + latch: QueryLatch, current: Option, ) -> (Q::Value, Option) where @@ -267,7 +265,7 @@ where match result { Ok(()) => { let Some((v, index)) = query.query_cache(qcx).lookup(&key) else { - cold_path(|| { + outline(|| { // We didn't find the query result in the query cache. Check if it was // poisoned due to a panic instead. let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); @@ -296,7 +294,7 @@ fn try_execute_query( qcx: Qcx, span: Span, key: Q::Key, - dep_node: Option>, + dep_node: Option, ) -> (Q::Value, Option) where Q: QueryConfig, @@ -364,10 +362,10 @@ where fn execute_job( query: Q, qcx: Qcx, - state: &QueryState, + state: &QueryState, key: Q::Key, id: QueryJobId, - dep_node: Option>, + dep_node: Option, ) -> (Q::Value, Option) where Q: QueryConfig, @@ -474,9 +472,9 @@ where fn execute_job_incr( query: Q, qcx: Qcx, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, key: Q::Key, - mut dep_node_opt: Option>, + mut dep_node_opt: Option, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where @@ -540,10 +538,10 @@ where #[inline(always)] fn try_load_from_disk_and_cache_in_memory( query: Q, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, qcx: Qcx, key: &Q::Key, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where Q: QueryConfig, @@ -637,7 +635,7 @@ where #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] pub(crate) fn incremental_verify_ich( tcx: Tcx, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, result: &V, prev_index: SerializedDepNodeIndex, hash_result: Option, &V) -> Fingerprint>, @@ -730,7 +728,7 @@ fn ensure_must_run( qcx: Qcx, key: &Q::Key, check_cache: bool, -) -> (bool, Option>) +) -> (bool, Option) where Q: QueryConfig, Qcx: QueryContext, @@ -821,12 +819,8 @@ where Some(result) } -pub fn force_query( - query: Q, - qcx: Qcx, - key: Q::Key, - dep_node: DepNode<::DepKind>, -) where +pub fn force_query(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) +where Q: QueryConfig, Qcx: QueryContext, { diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index 07c28fdb73b2e..8848fda9da3d0 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -1,14 +1,14 @@ use rustc_span::ErrorGuaranteed; -use crate::dep_graph::{DepContext, DepKind}; +use crate::dep_graph::DepContext; use crate::query::QueryInfo; -pub trait Value: Sized { - fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self; +pub trait Value: Sized { + fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self; } -impl Value for T { - default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> T { +impl Value for T { + default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> 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. diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 9a970f5db397e..272483d4a9876 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -130,9 +130,6 @@ resolve_generic_params_from_outer_item_ty_param = type parameter from outer item resolve_glob_import_doesnt_reexport = glob import doesn't reexport anything because no candidate is public enough -resolve_help_try_using_local_generic_param = - try using a local generic parameter instead - resolve_ident_bound_more_than_once_in_parameter_list = identifier `{$identifier}` is bound more than once in this parameter list .label = used as parameter more than once @@ -249,9 +246,6 @@ resolve_self_in_generic_param_default = generic parameters cannot use `Self` in their defaults .label = `Self` in generic parameter default -resolve_self_type_implicitly_declared_by_impl = - `Self` type implicitly declared here, by this `impl` - resolve_tool_module_imported = cannot use a tool module through an import .note = the tool module imported here @@ -267,12 +261,6 @@ resolve_trait_impl_mismatch = .label = does not match trait .label_trait_item = item in trait -resolve_try_adding_local_generic_param_on_method = - try adding a local generic parameter in this method instead - -resolve_try_using_local_generic_parameter = - try using a local generic parameter instead - resolve_try_using_similarly_named_label = try using similarly named label diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2c36c83ae728b..a18109574feb5 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -698,10 +698,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // These items live in the type namespace. ItemKind::TyAlias(..) => { - let res = Res::Def( - DefKind::TyAlias { lazy: self.r.tcx.features().lazy_type_alias }, - def_id, - ); + let res = Res::Def(DefKind::TyAlias, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } @@ -950,7 +947,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { DefKind::Struct | DefKind::Union | DefKind::Variant - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy | DefKind::TraitAlias diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9b7fd76d10310..110286255c5c9 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1169,6 +1169,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return; } + if ident.name == kw::Underscore { + return; + } + let child_accessible = accessible && this.is_accessible_from(name_binding.vis, parent_scope.module); @@ -2596,7 +2600,9 @@ fn show_candidates( ); if let [first, .., last] = &path[..] { let sp = first.ident.span.until(last.ident.span); - if sp.can_be_used_for_suggestions() { + // Our suggestion is empty, so make sure the span is not empty (or we'd ICE). + // Can happen for derive-generated spans. + if sp.can_be_used_for_suggestions() && !sp.is_empty() { err.span_suggestion_verbose( sp, format!("if you import `{}`, refer to it directly", last.ident), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 01f9f06059426..ece8b7f6ec96e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -41,9 +41,6 @@ type Res = def::Res; type IdentMap = FxHashMap; -/// Map from the name in a pattern to its binding mode. -type BindingMap = IdentMap; - use diagnostics::{ ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind, }; @@ -474,7 +471,7 @@ impl<'a> PathSource<'a> { | DefKind::Enum | DefKind::Trait | DefKind::TraitAlias - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy | DefKind::TyParam | DefKind::OpaqueTy @@ -513,7 +510,7 @@ impl<'a> PathSource<'a> { DefKind::Struct | DefKind::Union | DefKind::Variant - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy, _, ) | Res::SelfTyParam { .. } @@ -1766,7 +1763,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) | Res::Def(DefKind::Enum, def_id) - | Res::Def(DefKind::TyAlias { .. }, def_id) + | Res::Def(DefKind::TyAlias, def_id) | Res::Def(DefKind::Trait, def_id) if i + 1 == proj_start => { @@ -3164,8 +3161,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// this is done hygienically. This could arise for a macro /// that expands into an or-pattern where one 'x' was from the /// user and one 'x' came from the macro. - fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { - let mut binding_map = FxHashMap::default(); + fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap { + let mut binding_map = FxIndexMap::default(); pat.walk(&mut |pat| { match pat.kind { @@ -3200,22 +3197,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Checks that all of the arms in an or-pattern have exactly the /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings(&mut self, pats: &[P]) -> Vec { - let mut missing_vars = FxHashMap::default(); - let mut inconsistent_vars = FxHashMap::default(); + fn check_consistent_bindings( + &mut self, + pats: &[P], + ) -> Vec> { + // pats is consistent. + let mut missing_vars = FxIndexMap::default(); + let mut inconsistent_vars = FxIndexMap::default(); // 1) Compute the binding maps of all arms. let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::>(); // 2) Record any missing bindings or binding mode inconsistencies. - for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) { + for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { // Check against all arms except for the same pattern which is always self-consistent. - let inners = pats + let inners = maps .iter() - .enumerate() + .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) - .flat_map(|(idx, _)| maps[idx].iter()) - .map(|(key, binding)| (key.name, map_outer.get(&key), binding)); + .flat_map(|(map, _)| map) + .map(|(key, binding)| (key.name, map_outer.get(key), binding)); + + let inners = inners.collect::>(); for (name, info, &binding_inner) in inners { match info { @@ -3244,10 +3247,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } // 3) Report all missing variables we found. - let mut missing_vars = missing_vars.into_iter().collect::>(); - missing_vars.sort_by_key(|&(sym, ref _err)| sym); - - for (name, mut v) in missing_vars.into_iter() { + for (name, mut v) in missing_vars { if inconsistent_vars.contains_key(&name) { v.could_be_path = false; } @@ -3258,10 +3258,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } // 4) Report all inconsistencies in binding modes we found. - let mut inconsistent_vars = inconsistent_vars.iter().collect::>(); - inconsistent_vars.sort(); for (name, v) in inconsistent_vars { - self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1)); + self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1)); } // 5) Finally bubble up all the binding maps. @@ -4140,6 +4138,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } + fn resolve_expr_field(&mut self, f: &'ast ExprField, e: &'ast Expr) { + self.resolve_expr(&f.expr, Some(e)); + self.visit_ident(f.ident); + walk_list!(self, visit_attribute, f.attrs.iter()); + } + fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -4155,7 +4159,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ExprKind::Struct(ref se) => { self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct); - visit::walk_expr(self, expr); + // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the + // parent in for accurate suggestions when encountering `Foo { bar }` that should + // have been `Foo { bar: self.bar }`. + if let Some(qself) = &se.qself { + self.visit_ty(&qself.ty); + } + self.visit_path(&se.path, expr.id); + walk_list!(self, resolve_expr_field, &se.fields, expr); + match &se.rest { + StructRest::Base(expr) => self.visit_expr(expr), + StructRest::Rest(_span) => {} + StructRest::None => {} + } } ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c34b7df9b4603..bc5f8a37b0ff4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -41,7 +41,7 @@ type Res = def::Res; /// A field or associated item from self type suggested in case of resolution failure. enum AssocSuggestion { - Field, + Field(Span), MethodWithSelf { called: bool }, AssocFn { called: bool }, AssocType, @@ -51,7 +51,7 @@ enum AssocSuggestion { impl AssocSuggestion { fn action(&self) -> &'static str { match self { - AssocSuggestion::Field => "use the available field", + AssocSuggestion::Field(_) => "use the available field", AssocSuggestion::MethodWithSelf { called: true } => { "call the method with the fully-qualified path" } @@ -186,7 +186,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fallback_label: format!("not a {expected}"), span, span_label: match res { - Res::Def(kind, def_id) if kind == DefKind::TyParam => { + Res::Def(DefKind::TyParam, def_id) => { Some((self.r.def_span(def_id), "found this type parameter")) } _ => None, @@ -214,7 +214,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { module: None, } } else { - let item_span = path.last().unwrap().ident.span; + let mut span_label = None; + let item_ident = path.last().unwrap().ident; + let item_span = item_ident.span; let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 { debug!(?self.diagnostic_metadata.current_impl_items); debug!(?self.diagnostic_metadata.current_function); @@ -224,32 +226,75 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { && let FnKind::Fn(_, _, sig, ..) = fn_kind && let Some(items) = self.diagnostic_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind - && i.ident.name == item_str.name - // don't suggest if the item is in Fn signature arguments - // issue #112590 + i.ident.name == item_str.name + // Don't suggest if the item is in Fn signature arguments (#112590). && !sig.span.contains(item_span) - { - debug!(?item_str.name); - return true - } - false }) { - let self_sugg = match &item.kind { - AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.", - _ => "Self::", + let sp = item_span.shrink_to_lo(); + + // Account for `Foo { field }` when suggesting `self.field` so we result on + // `Foo { field: self.field }`. + let field = match source { + PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. })) => { + expr.fields.iter().find(|f| f.ident == item_ident) + } + _ => None, + }; + let pre = if let Some(field) = field && field.is_shorthand { + format!("{item_ident}: ") + } else { + String::new() + }; + // Ensure we provide a structured suggestion for an assoc fn only for + // expressions that are actually a fn call. + let is_call = match field { + Some(ast::ExprField { expr, .. }) => { + matches!(expr.kind, ExprKind::Call(..)) + } + _ => matches!( + source, + PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), ..})), + ), }; - Some(( - item_span.shrink_to_lo(), - match &item.kind { - AssocItemKind::Fn(..) => "consider using the associated function", - AssocItemKind::Const(..) => "consider using the associated constant", - _ => unreachable!("item kind was filtered above"), - }, - self_sugg.to_string() - )) + match &item.kind { + AssocItemKind::Fn(fn_) + if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() => { + // Ensure that we only suggest `self.` if `self` is available, + // you can't call `fn foo(&self)` from `fn bar()` (#115992). + // We also want to mention that the method exists. + span_label = Some(( + item.ident.span, + "a method by that name is available on `Self` here", + )); + None + } + AssocItemKind::Fn(fn_) + if !fn_.sig.decl.has_self() && !is_call => { + span_label = Some(( + item.ident.span, + "an associated function by that name is available on `Self` here", + )); + None + } + AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some(( + sp, + "consider using the method on `Self`", + format!("{pre}self."), + )), + AssocItemKind::Fn(_) => Some(( + sp, + "consider using the associated function on `Self`", + format!("{pre}Self::"), + )), + AssocItemKind::Const(..) => Some(( + sp, + "consider using the associated constant on `Self`", + format!("{pre}Self::"), + )), + _ => None + } } else { None }; @@ -314,7 +359,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"), fallback_label, span: item_span, - span_label: None, + span_label, could_be_expr: false, suggestion, module, @@ -611,17 +656,30 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) { let self_is_available = self.self_value_is_available(path[0].ident.span); + // Account for `Foo { field }` when suggesting `self.field` so we result on + // `Foo { field: self.field }`. + let pre = match source { + PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. })) + if expr + .fields + .iter() + .any(|f| f.ident == path[0].ident && f.is_shorthand) => + { + format!("{path_str}: ") + } + _ => String::new(), + }; match candidate { - AssocSuggestion::Field => { + AssocSuggestion::Field(field_span) => { if self_is_available { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), "you might have meant to use the available field", - format!("self.{path_str}"), + format!("{pre}self."), Applicability::MachineApplicable, ); } else { - err.span_label(span, "a field by this name exists in `Self`"); + err.span_label(field_span, "a field by that name exists in `Self`"); } } AssocSuggestion::MethodWithSelf { called } if self_is_available => { @@ -630,10 +688,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } else { "you might have meant to refer to the method" }; - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), msg, - format!("self.{path_str}"), + "self.".to_string(), Applicability::MachineApplicable, ); } @@ -641,10 +699,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | AssocSuggestion::AssocFn { .. } | AssocSuggestion::AssocConst | AssocSuggestion::AssocType => { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), format!("you might have meant to {}", candidate.action()), - format!("Self::{path_str}"), + "Self::".to_string(), Applicability::MachineApplicable, ); } @@ -1419,7 +1477,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => { err.span_label(span, fallback_label.to_string()); } - (Res::Def(DefKind::TyAlias { .. }, def_id), PathSource::Trait(_)) => { + (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => { err.span_label(span, "type aliases cannot be used as traits"); if self.r.tcx.sess.is_nightly_build() { let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ @@ -1588,7 +1646,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_label(span, fallback_label.to_string()); err.note("can't use `Self` as a constructor, you must use the implemented struct"); } - (Res::Def(DefKind::TyAlias { .. } | DefKind::AssocTy, _), _) if ns == ValueNS => { + (Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => { err.note("can't use a type alias as a constructor"); } _ => return false, @@ -1657,11 +1715,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { resolution.full_res() { if let Some(field_ids) = self.r.field_def_ids(did) { - if field_ids + if let Some(field_id) = field_ids .iter() - .any(|&field_id| ident.name == self.r.tcx.item_name(field_id)) + .find(|&&field_id| ident.name == self.r.tcx.item_name(field_id)) { - return Some(AssocSuggestion::Field); + return Some(AssocSuggestion::Field(self.r.def_span(*field_id))); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 949c6ab5ac0c1..5f012ec29fe00 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1074,8 +1074,8 @@ pub struct Resolver<'a, 'tcx> { /// Also includes of list of each fields visibility struct_constructors: LocalDefIdMap<(Res, ty::Visibility, Vec>)>, - /// Features enabled for this crate. - active_features: FxHashSet, + /// Features declared for this crate. + declared_features: FxHashSet, lint_buffer: LintBuffer, @@ -1417,12 +1417,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { multi_segment_macro_resolutions: Default::default(), builtin_attrs: Default::default(), containers_deriving_copy: Default::default(), - active_features: features - .declared_lib_features - .iter() - .map(|(feat, ..)| *feat) - .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) - .collect(), + declared_features: features.declared_features.clone(), lint_buffer: LintBuffer::default(), next_node_id: CRATE_NODE_ID, node_id_to_def_id, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 90ae08ce37c1f..f0a1a4ff931e9 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -854,7 +854,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let feature = stability.feature; let is_allowed = |feature| { - self.active_features.contains(&feature) || span.allows_unstable(feature) + self.declared_features.contains(&feature) || span.allows_unstable(feature) }; let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature)); if !is_allowed(feature) && !allowed_by_implication { diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs deleted file mode 100644 index 8f8c504117cc1..0000000000000 --- a/compiler/rustc_serialize/src/collection_impls.rs +++ /dev/null @@ -1,279 +0,0 @@ -//! Implementations of serialization for structures found in liballoc - -use crate::{Decodable, Decoder, Encodable, Encoder}; -use smallvec::{Array, SmallVec}; -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque}; -use std::hash::{BuildHasher, Hash}; -use std::rc::Rc; -use std::sync::Arc; -use thin_vec::ThinVec; - -impl>> Encodable for SmallVec { - fn encode(&self, s: &mut S) { - let slice: &[A::Item] = self; - slice.encode(s); - } -} - -impl>> Decodable for SmallVec { - fn decode(d: &mut D) -> SmallVec { - let len = d.read_usize(); - (0..len).map(|_| Decodable::decode(d)).collect() - } -} - -impl> Encodable for ThinVec { - fn encode(&self, s: &mut S) { - self.as_slice().encode(s); - } -} - -impl> Decodable for ThinVec { - fn decode(d: &mut D) -> ThinVec { - let len = d.read_usize(); - (0..len).map(|_| Decodable::decode(d)).collect() - } -} - -impl> Encodable for LinkedList { - fn encode(&self, s: &mut S) { - s.emit_usize(self.len()); - for e in self.iter() { - e.encode(s); - } - } -} - -impl> Decodable for LinkedList { - fn decode(d: &mut D) -> LinkedList { - let len = d.read_usize(); - (0..len).map(|_| Decodable::decode(d)).collect() - } -} - -impl> Encodable for VecDeque { - fn encode(&self, s: &mut S) { - s.emit_usize(self.len()); - for e in self.iter() { - e.encode(s); - } - } -} - -impl> Decodable for VecDeque { - fn decode(d: &mut D) -> VecDeque { - let len = d.read_usize(); - (0..len).map(|_| Decodable::decode(d)).collect() - } -} - -impl Encodable for BTreeMap -where - K: Encodable + PartialEq + Ord, - V: Encodable, -{ - fn encode(&self, e: &mut S) { - e.emit_usize(self.len()); - for (key, val) in self.iter() { - key.encode(e); - val.encode(e); - } - } -} - -impl Decodable for BTreeMap -where - K: Decodable + PartialEq + Ord, - V: Decodable, -{ - fn decode(d: &mut D) -> BTreeMap { - let len = d.read_usize(); - let mut map = BTreeMap::new(); - for _ in 0..len { - let key = Decodable::decode(d); - let val = Decodable::decode(d); - map.insert(key, val); - } - map - } -} - -impl Encodable for BTreeSet -where - T: Encodable + PartialEq + Ord, -{ - fn encode(&self, s: &mut S) { - s.emit_usize(self.len()); - for e in self.iter() { - e.encode(s); - } - } -} - -impl Decodable for BTreeSet -where - T: Decodable + PartialEq + Ord, -{ - fn decode(d: &mut D) -> BTreeSet { - let len = d.read_usize(); - let mut set = BTreeSet::new(); - for _ in 0..len { - set.insert(Decodable::decode(d)); - } - set - } -} - -impl Encodable for HashMap -where - K: Encodable + Eq, - V: Encodable, - S: BuildHasher, -{ - fn encode(&self, e: &mut E) { - e.emit_usize(self.len()); - for (key, val) in self.iter() { - key.encode(e); - val.encode(e); - } - } -} - -impl Decodable for HashMap -where - K: Decodable + Hash + Eq, - V: Decodable, - S: BuildHasher + Default, -{ - fn decode(d: &mut D) -> HashMap { - let len = d.read_usize(); - let state = Default::default(); - let mut map = HashMap::with_capacity_and_hasher(len, state); - for _ in 0..len { - let key = Decodable::decode(d); - let val = Decodable::decode(d); - map.insert(key, val); - } - map - } -} - -impl Encodable for HashSet -where - T: Encodable + Eq, - S: BuildHasher, -{ - fn encode(&self, s: &mut E) { - s.emit_usize(self.len()); - for e in self.iter() { - e.encode(s); - } - } -} - -impl Decodable for HashSet -where - T: Decodable + Hash + Eq, - S: BuildHasher + Default, -{ - fn decode(d: &mut D) -> HashSet { - let len = d.read_usize(); - let state = Default::default(); - let mut set = HashSet::with_capacity_and_hasher(len, state); - for _ in 0..len { - set.insert(Decodable::decode(d)); - } - set - } -} - -impl Encodable for indexmap::IndexMap -where - K: Encodable + Hash + Eq, - V: Encodable, - S: BuildHasher, -{ - fn encode(&self, e: &mut E) { - e.emit_usize(self.len()); - for (key, val) in self.iter() { - key.encode(e); - val.encode(e); - } - } -} - -impl Decodable for indexmap::IndexMap -where - K: Decodable + Hash + Eq, - V: Decodable, - S: BuildHasher + Default, -{ - fn decode(d: &mut D) -> indexmap::IndexMap { - let len = d.read_usize(); - let state = Default::default(); - let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state); - for _ in 0..len { - let key = Decodable::decode(d); - let val = Decodable::decode(d); - map.insert(key, val); - } - map - } -} - -impl Encodable for indexmap::IndexSet -where - T: Encodable + Hash + Eq, - S: BuildHasher, -{ - fn encode(&self, s: &mut E) { - s.emit_usize(self.len()); - for e in self.iter() { - e.encode(s); - } - } -} - -impl Decodable for indexmap::IndexSet -where - T: Decodable + Hash + Eq, - S: BuildHasher + Default, -{ - fn decode(d: &mut D) -> indexmap::IndexSet { - let len = d.read_usize(); - let state = Default::default(); - let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state); - for _ in 0..len { - set.insert(Decodable::decode(d)); - } - set - } -} - -impl> Encodable for Rc<[T]> { - fn encode(&self, s: &mut E) { - let slice: &[T] = self; - slice.encode(s); - } -} - -impl> Decodable for Rc<[T]> { - fn decode(d: &mut D) -> Rc<[T]> { - let vec: Vec = Decodable::decode(d); - vec.into() - } -} - -impl> Encodable for Arc<[T]> { - fn encode(&self, s: &mut E) { - let slice: &[T] = self; - slice.encode(s); - } -} - -impl> Decodable for Arc<[T]> { - fn decode(d: &mut D) -> Arc<[T]> { - let vec: Vec = Decodable::decode(d); - vec.into() - } -} diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index dd40b3cf0283d..5360aa9ea6a94 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -1,25 +1,19 @@ //! Support code for encoding and decoding types. -/* -Core encoding and decoding interfaces. -*/ - #![doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", html_playground_url = "https://play.rust-lang.org/", test(attr(allow(unused_variables), deny(warnings))) )] -#![feature(never_type)] +#![feature(allocator_api)] #![feature(associated_type_bounds)] -#![feature(min_specialization)] +#![feature(const_option)] #![feature(core_intrinsics)] -#![feature(maybe_uninit_slice)] -#![feature(new_uninit)] -#![feature(allocator_api)] +#![feature(inline_const)] +#![feature(min_specialization)] +#![feature(never_type)] #![feature(ptr_sub_ptr)] #![feature(slice_first_last_chunk)] -#![feature(inline_const)] -#![feature(const_option)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] #![deny(rustc::untranslatable_diagnostic)] @@ -27,7 +21,6 @@ Core encoding and decoding interfaces. pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; -mod collection_impls; mod serialize; pub mod leb128; diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 44855ae629c13..552554390515c 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -38,11 +38,16 @@ pub struct FileEncoder { impl FileEncoder { pub fn new>(path: P) -> io::Result { + // File::create opens the file for writing only. When -Zmeta-stats is enabled, the metadata + // encoder rewinds the file to inspect what was written. So we need to always open the file + // for reading and writing. + let file = File::options().read(true).write(true).create(true).truncate(true).open(path)?; + Ok(FileEncoder { buf: vec![0u8; BUF_SIZE].into_boxed_slice().try_into().unwrap(), buffered: 0, flushed: 0, - file: File::create(path)?, + file, res: Ok(()), }) } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 06166cabc1872..63bd3457eb97c 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -1,12 +1,15 @@ //! Support code for encoding and decoding types. -use std::alloc::Allocator; +use smallvec::{Array, SmallVec}; use std::borrow::Cow; use std::cell::{Cell, RefCell}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}; +use std::hash::{BuildHasher, Hash}; use std::marker::PhantomData; use std::path; use std::rc::Rc; use std::sync::Arc; +use thin_vec::ThinVec; /// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string. /// This way we can skip validation and still be relatively sure that deserialization @@ -273,9 +276,9 @@ impl Decodable for PhantomData { } } -impl> Decodable for Box<[T], A> { - fn decode(d: &mut D) -> Box<[T], A> { - let v: Vec = Decodable::decode(d); +impl> Decodable for Box<[T]> { + fn decode(d: &mut D) -> Box<[T]> { + let v: Vec = Decodable::decode(d); v.into_boxed_slice() } } @@ -303,33 +306,20 @@ impl> Encodable for [T] { impl> Encodable for Vec { fn encode(&self, s: &mut S) { - let slice: &[T] = self; - slice.encode(s); + self.as_slice().encode(s); } } -impl, A: Allocator + Default> Decodable for Vec { - default fn decode(d: &mut D) -> Vec { +impl> Decodable for Vec { + default fn decode(d: &mut D) -> Vec { let len = d.read_usize(); - let allocator = A::default(); - // SAFETY: we set the capacity in advance, only write elements, and - // only set the length at the end once the writing has succeeded. - let mut vec = Vec::with_capacity_in(len, allocator); - unsafe { - let ptr: *mut T = vec.as_mut_ptr(); - for i in 0..len { - std::ptr::write(ptr.add(i), Decodable::decode(d)); - } - vec.set_len(len); - } - vec + (0..len).map(|_| Decodable::decode(d)).collect() } } impl, const N: usize> Encodable for [T; N] { fn encode(&self, s: &mut S) { - let slice: &[T] = self; - slice.encode(s); + self.as_slice().encode(s); } } @@ -497,15 +487,233 @@ impl> Decodable for Arc { } } -impl, A: Allocator + Default> Encodable for Box { +impl> Encodable for Box { fn encode(&self, s: &mut S) { (**self).encode(s) } } -impl> Decodable for Box { - fn decode(d: &mut D) -> Box { - let allocator = A::default(); - Box::new_in(Decodable::decode(d), allocator) +impl> Decodable for Box { + fn decode(d: &mut D) -> Box { + Box::new(Decodable::decode(d)) + } +} + +impl>> Encodable for SmallVec { + fn encode(&self, s: &mut S) { + self.as_slice().encode(s); + } +} + +impl>> Decodable for SmallVec { + fn decode(d: &mut D) -> SmallVec { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl> Encodable for ThinVec { + fn encode(&self, s: &mut S) { + self.as_slice().encode(s); + } +} + +impl> Decodable for ThinVec { + fn decode(d: &mut D) -> ThinVec { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl> Encodable for VecDeque { + fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); + for e in self.iter() { + e.encode(s); + } + } +} + +impl> Decodable for VecDeque { + fn decode(d: &mut D) -> VecDeque { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl Encodable for BTreeMap +where + K: Encodable + PartialEq + Ord, + V: Encodable, +{ + fn encode(&self, e: &mut S) { + e.emit_usize(self.len()); + for (key, val) in self.iter() { + key.encode(e); + val.encode(e); + } + } +} + +impl Decodable for BTreeMap +where + K: Decodable + PartialEq + Ord, + V: Decodable, +{ + fn decode(d: &mut D) -> BTreeMap { + let len = d.read_usize(); + (0..len).map(|_| (Decodable::decode(d), Decodable::decode(d))).collect() + } +} + +impl Encodable for BTreeSet +where + T: Encodable + PartialEq + Ord, +{ + fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); + for e in self.iter() { + e.encode(s); + } + } +} + +impl Decodable for BTreeSet +where + T: Decodable + PartialEq + Ord, +{ + fn decode(d: &mut D) -> BTreeSet { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl Encodable for HashMap +where + K: Encodable + Eq, + V: Encodable, + S: BuildHasher, +{ + fn encode(&self, e: &mut E) { + e.emit_usize(self.len()); + for (key, val) in self.iter() { + key.encode(e); + val.encode(e); + } + } +} + +impl Decodable for HashMap +where + K: Decodable + Hash + Eq, + V: Decodable, + S: BuildHasher + Default, +{ + fn decode(d: &mut D) -> HashMap { + let len = d.read_usize(); + (0..len).map(|_| (Decodable::decode(d), Decodable::decode(d))).collect() + } +} + +impl Encodable for HashSet +where + T: Encodable + Eq, + S: BuildHasher, +{ + fn encode(&self, s: &mut E) { + s.emit_usize(self.len()); + for e in self.iter() { + e.encode(s); + } + } +} + +impl Decodable for HashSet +where + T: Decodable + Hash + Eq, + S: BuildHasher + Default, +{ + fn decode(d: &mut D) -> HashSet { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl Encodable for indexmap::IndexMap +where + K: Encodable + Hash + Eq, + V: Encodable, + S: BuildHasher, +{ + fn encode(&self, e: &mut E) { + e.emit_usize(self.len()); + for (key, val) in self.iter() { + key.encode(e); + val.encode(e); + } + } +} + +impl Decodable for indexmap::IndexMap +where + K: Decodable + Hash + Eq, + V: Decodable, + S: BuildHasher + Default, +{ + fn decode(d: &mut D) -> indexmap::IndexMap { + let len = d.read_usize(); + (0..len).map(|_| (Decodable::decode(d), Decodable::decode(d))).collect() + } +} + +impl Encodable for indexmap::IndexSet +where + T: Encodable + Hash + Eq, + S: BuildHasher, +{ + fn encode(&self, s: &mut E) { + s.emit_usize(self.len()); + for e in self.iter() { + e.encode(s); + } + } +} + +impl Decodable for indexmap::IndexSet +where + T: Decodable + Hash + Eq, + S: BuildHasher + Default, +{ + fn decode(d: &mut D) -> indexmap::IndexSet { + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() + } +} + +impl> Encodable for Rc<[T]> { + fn encode(&self, s: &mut E) { + let slice: &[T] = self; + slice.encode(s); + } +} + +impl> Decodable for Rc<[T]> { + fn decode(d: &mut D) -> Rc<[T]> { + let vec: Vec = Decodable::decode(d); + vec.into() + } +} + +impl> Encodable for Arc<[T]> { + fn encode(&self, s: &mut E) { + let slice: &[T] = self; + slice.encode(s); + } +} + +impl> Decodable for Arc<[T]> { + fn decode(d: &mut D) -> Arc<[T]> { + let vec: Vec = Decodable::decode(d); + vec.into() } } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index e06b638094452..b356b503aa541 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -25,8 +25,6 @@ session_feature_diagnostic_for_issue = session_feature_diagnostic_help = add `#![feature({$feature})]` to the crate attributes to enable -session_feature_gate_error = {$explain} - session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions session_file_write_fail = failed to write `{$path}` due to error `{$err}` diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 956ae149e5545..3970b751af771 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -813,7 +813,6 @@ impl Input { FileName::Anon(_) => None, FileName::MacroExpansion(_) => None, FileName::ProcMacroSourceCode(_) => None, - FileName::CfgSpec(_) => None, FileName::CliCrateAttr(_) => None, FileName::Custom(_) => None, FileName::DocTest(path, _) => Some(path), @@ -2475,6 +2474,19 @@ pub fn parse_externs( Some((opts, name)) => (Some(opts), name.to_string()), }; + if !crate::utils::is_ascii_ident(&name) { + let mut error = handler.early_struct_error(format!( + "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" + )); + let adjusted_name = name.replace("-", "_"); + if crate::utils::is_ascii_ident(&adjusted_name) { + error.help(format!( + "consider replacing the dashes with underscores: `{adjusted_name}`" + )); + } + error.emit(); + } + let path = path.map(|p| CanonicalizedPath::new(p)); let entry = externs.entry(name.to_owned()); @@ -3155,9 +3167,9 @@ impl PpMode { pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, InstrumentCoverage, InstrumentXRay, LdImpl, LinkerPluginLto, - LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, - Passes, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, + ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, + LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Passes, + ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, }; use crate::lint; @@ -3254,7 +3266,6 @@ pub(crate) mod dep_tracking { SymbolManglingVersion, SourceFileHashAlgorithm, TrimmedDefPaths, - Option, OutFileName, OutputType, RealFileName, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5a6def1958bd0..f7c000c8bd6ed 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -20,7 +20,7 @@ use std::collections::BTreeMap; use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; -use std::num::NonZeroUsize; +use std::num::{IntErrorKind, NonZeroUsize}; use std::path::PathBuf; use std::str; @@ -387,7 +387,7 @@ mod desc { "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; - pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; + pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub const parse_trait_solver: &str = "one of the supported solver modes (`classic`, `next`, or `next-coherence`)"; pub const parse_lto: &str = @@ -412,7 +412,6 @@ mod desc { "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; pub const parse_split_dwarf_kind: &str = "one of supported split dwarf modes (`split` or `single`)"; - pub const parse_gcc_ld: &str = "one of: no value, `lld`"; pub const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \ components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`"; pub const parse_stack_protector: &str = @@ -986,10 +985,16 @@ mod parse { pub(crate) fn parse_treat_err_as_bug(slot: &mut Option, v: Option<&str>) -> bool { match v { - Some(s) => { - *slot = s.parse().ok(); - slot.is_some() - } + Some(s) => match s.parse() { + Ok(val) => { + *slot = Some(val); + true + } + Err(e) => { + *slot = None; + e.kind() == &IntErrorKind::Zero + } + }, None => { *slot = NonZeroUsize::new(1); true @@ -1196,15 +1201,6 @@ mod parse { true } - pub(crate) fn parse_gcc_ld(slot: &mut Option, v: Option<&str>) -> bool { - match v { - None => *slot = None, - Some("lld") => *slot = Some(LdImpl::Lld), - _ => return false, - } - true - } - pub(crate) fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool { match v.and_then(|s| StackProtector::from_str(s).ok()) { Some(ssp) => *slot = ssp, @@ -1452,17 +1448,11 @@ options! { dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED], "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \ (default: no)"), - drop_tracking: bool = (false, parse_bool, [TRACKED], - "enables drop tracking in generators (default: no)"), - drop_tracking_mir: bool = (false, parse_bool, [TRACKED], - "enables drop tracking on MIR in generators (default: no)"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) \ (default: no)"), - dump_drop_tracking_cfg: Option = (None, parse_opt_string, [UNTRACKED], - "dump drop-tracking control-flow graph as a `.dot` file (default: no)"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state to file. `val` is used to select which passes and functions to dump. For example: @@ -1521,7 +1511,6 @@ options! { "whether each function should go in its own section"), future_incompat_test: bool = (false, parse_bool, [UNTRACKED], "forces all lints to be future incompatible, used for internal testing (default: no)"), - gcc_ld: Option = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"), graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED], "use dark-themed colors in graphviz output (default: no)"), graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED], @@ -1846,7 +1835,8 @@ written to standard error output)"), trap_unreachable: Option = (None, parse_opt_bool, [TRACKED], "generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)"), treat_err_as_bug: Option = (None, parse_treat_err_as_bug, [TRACKED], - "treat error number `val` that occurs as bug"), + "treat the `val`th error that occurs as bug (default if not specified: 0 - don't treat errors as bugs. \ + default if specified without a value: 1 - treat the first error as bug)"), trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED], "in diagnostics, use heuristics to shorten paths referring to items"), tune_cpu: Option = (None, parse_opt_string, [TRACKED], @@ -1905,8 +1895,3 @@ pub enum WasiExecModel { Command, Reactor, } - -#[derive(Clone, Copy, Hash)] -pub enum LdImpl { - Lld, -} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 86f4e7b48dab5..b484978eed230 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1724,6 +1724,15 @@ impl EarlyErrorHandler { self.handler.struct_fatal(msg).emit() } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub(crate) fn early_struct_error( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, !> { + self.handler.struct_fatal(msg) + } + #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] pub fn early_warn(&self, msg: impl Into) { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index f76c69af526e9..aea7c6c284286 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -158,3 +158,12 @@ pub fn extra_compiler_flags() -> Option<(Vec, bool)> { if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } } + +pub(crate) fn is_ascii_ident(string: &str) -> bool { + let mut chars = string.chars(); + if let Some(start) = chars.next() && (start.is_ascii_alphabetic() || start == '_') { + chars.all(|char| char.is_ascii_alphanumeric() || char == '_') + } else { + false + } +} diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 21ec904e43c58..3e0d6baab6aab 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,24 +4,13 @@ version = "0.0.0" edition = "2021" [dependencies] -# Use optional dependencies for rustc_* in order to support building this crate separately. -rustc_hir = { path = "../rustc_hir", optional = true } -rustc_middle = { path = "../rustc_middle", optional = true } -rustc_span = { path = "../rustc_span", optional = true } -rustc_target = { path = "../rustc_target", optional = true } -rustc_driver = { path = "../rustc_driver", optional = true } -rustc_interface = { path = "../rustc_interface", optional = true} -rustc_session = {path = "../rustc_session", optional = true} +rustc_driver = { path = "../rustc_driver" } +rustc_hir = { path = "../rustc_hir" } +rustc_interface = { path = "../rustc_interface" } +rustc_middle = { path = "../rustc_middle" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } +stable_mir = {path = "../stable_mir" } tracing = "0.1" -scoped-tls = "1.0" [features] -default = [ - "rustc_hir", - "rustc_middle", - "rustc_span", - "rustc_target", - "rustc_driver", - "rustc_interface", - "rustc_session", -] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 8cb533c8d6726..d10f46fad9e28 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -10,26 +10,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] -#![cfg_attr(not(feature = "default"), feature(rustc_private))] -#![feature(ptr_metadata)] -#![feature(type_alias_impl_trait)] // Used to define opaque types. -#![feature(intra_doc_pointers)] - -// Declare extern rustc_* crates to enable building this crate separately from the compiler. -#[cfg(not(feature = "default"))] -extern crate rustc_hir; -#[cfg(not(feature = "default"))] -extern crate rustc_middle; -#[cfg(not(feature = "default"))] -extern crate rustc_span; -#[cfg(not(feature = "default"))] -extern crate rustc_target; pub mod rustc_internal; -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_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 10ee5af86c627..36eb2247253a0 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,75 +3,17 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use std::fmt::Debug; use std::ops::{ControlFlow, Index}; use crate::rustc_internal; -use crate::stable_mir::CompilerError; -use crate::{ - rustc_smir::Tables, - stable_mir::{self, with}, -}; +use crate::rustc_smir::Tables; use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; use rustc_middle::ty::TyCtxt; -pub use rustc_span::def_id::{CrateNum, DefId}; +use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; - -fn with_tables(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R { - let mut ret = None; - with(|tables| tables.rustc_tables(&mut |t| ret = Some(f(t)))); - ret.unwrap() -} - -pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId { - with_tables(|t| t[item.0]) -} - -pub fn crate_item(did: DefId) -> stable_mir::CrateItem { - with_tables(|t| t.crate_item(did)) -} - -pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef { - with_tables(|t| t.adt_def(did)) -} - -pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef { - with_tables(|t| t.foreign_def(did)) -} - -pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef { - with_tables(|t| t.fn_def(did)) -} - -pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef { - with_tables(|t| t.closure_def(did)) -} - -pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef { - with_tables(|t| t.generator_def(did)) -} - -pub fn alias_def(did: DefId) -> stable_mir::ty::AliasDef { - with_tables(|t| t.alias_def(did)) -} - -pub fn param_def(did: DefId) -> stable_mir::ty::ParamDef { - with_tables(|t| t.param_def(did)) -} - -pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef { - with_tables(|t| t.br_named_def(did)) -} - -pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef { - with_tables(|t| t.trait_def(did)) -} - -pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef { - with_tables(|t| t.impl_def(did)) -} +use stable_mir::CompilerError; impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -82,6 +24,15 @@ impl<'tcx> Index for Tables<'tcx> { } } +impl<'tcx> Index for Tables<'tcx> { + type Output = Span; + + #[inline(always)] + fn index(&self, index: stable_mir::ty::Span) -> &Self::Output { + &self.spans[index.0] + } +} + impl<'tcx> Tables<'tcx> { pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem { stable_mir::CrateItem(self.create_def_id(did)) @@ -135,6 +86,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::ImplDef(self.create_def_id(did)) } + pub fn region_def(&mut self, did: DefId) -> stable_mir::ty::RegionDef { + stable_mir::ty::RegionDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } @@ -178,32 +133,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - crate::stable_mir::run( + stable_mir::run( Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] }, f, ); } -/// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone)] -pub struct Opaque(String); - -impl std::fmt::Display for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) - } -} - -pub(crate) fn opaque(value: &T) -> Opaque { - Opaque(format!("{value:?}")) -} - pub struct StableMir where B: Send, diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index d8766cf8ce23e..63a2a145069ee 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -3,11 +3,9 @@ use rustc_middle::mir::{ ConstValue, }; -use crate::{ - rustc_smir::{Stable, Tables}, - stable_mir::mir::Mutability, - stable_mir::ty::{Allocation, ProvenanceMap}, -}; +use crate::rustc_smir::{Stable, Tables}; +use stable_mir::mir::Mutability; +use stable_mir::ty::{Allocation, ProvenanceMap}; /// Creates new empty `Allocation` from given `Align`. fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 93b5b9654d35d..0c474192240d4 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,19 +7,17 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. -use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; -use crate::stable_mir::ty::{ - FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy, -}; -use crate::stable_mir::{self, CompilerError, Context}; +use crate::rustc_smir::hir::def::DefKind; +use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region}; use rustc_hir as hir; +use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; -use rustc_middle::mir::{self, ConstantKind}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_span::ErrorGuaranteed; use rustc_target::abi::FieldIdx; +use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; +use stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy}; +use stable_mir::{self, opaque, Context}; use tracing::debug; mod alloc; @@ -33,17 +31,32 @@ impl<'tcx> Context for Tables<'tcx> { self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect() } - fn find_crate(&self, name: &str) -> Option { - [LOCAL_CRATE].iter().chain(self.tcx.crates(()).iter()).find_map(|crate_num| { - let crate_name = self.tcx.crate_name(*crate_num).to_string(); - (name == crate_name).then(|| smir_crate(self.tcx, *crate_num)) - }) + fn find_crates(&self, name: &str) -> Vec { + let crates: Vec = [LOCAL_CRATE] + .iter() + .chain(self.tcx.crates(()).iter()) + .map(|crate_num| { + let crate_name = self.tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(self.tcx, *crate_num)) + }) + .into_iter() + .filter_map(|c| c) + .collect(); + crates } fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String { self.tcx.def_path_str(self[def_id]) } + fn print_span(&self, span: stable_mir::ty::Span) -> String { + self.tcx.sess.source_map().span_to_diagnostic_string(self[span]) + } + + fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind { + self.tcx.def_kind(self[def_id]).stable(self) + } + fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { self.tcx.def_span(self[def_id]).stable(self) } @@ -100,15 +113,18 @@ impl<'tcx> Context for Tables<'tcx> { .collect(), }) .collect(), - locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(), + locals: mir + .local_decls + .iter() + .map(|decl| stable_mir::mir::LocalDecl { + ty: self.intern_ty(decl.ty), + span: decl.source_info.span.stable(self), + }) + .collect(), } } - fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)) { - f(self) - } - - fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind { + fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { self.types[ty.0].clone().stable(self) } @@ -221,41 +237,64 @@ pub(crate) trait Stable<'tcx> { impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::StatementKind::*; - match &self.kind { - Assign(assign) => { - stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables)) - } - FakeRead(fake_read_place) => stable_mir::mir::Statement::FakeRead( - fake_read_place.0.stable(tables), - fake_read_place.1.stable(tables), + Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { + type T = stable_mir::mir::StatementKind; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + match self { + mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign( + assign.0.stable(tables), + assign.1.stable(tables), ), - SetDiscriminant { place: plc, variant_index: idx } => { - stable_mir::mir::Statement::SetDiscriminant { - place: plc.as_ref().stable(tables), - variant_index: idx.stable(tables), + mir::StatementKind::FakeRead(fake_read_place) => { + stable_mir::mir::StatementKind::FakeRead( + fake_read_place.0.stable(tables), + fake_read_place.1.stable(tables), + ) + } + mir::StatementKind::SetDiscriminant { place, variant_index } => { + stable_mir::mir::StatementKind::SetDiscriminant { + place: place.as_ref().stable(tables), + variant_index: variant_index.stable(tables), } } - Deinit(place) => stable_mir::mir::Statement::Deinit(place.stable(tables)), - StorageLive(place) => stable_mir::mir::Statement::StorageLive(place.stable(tables)), - StorageDead(place) => stable_mir::mir::Statement::StorageDead(place.stable(tables)), - Retag(retag, place) => { - stable_mir::mir::Statement::Retag(retag.stable(tables), place.stable(tables)) + mir::StatementKind::Deinit(place) => { + stable_mir::mir::StatementKind::Deinit(place.stable(tables)) + } + + mir::StatementKind::StorageLive(place) => { + stable_mir::mir::StatementKind::StorageLive(place.stable(tables)) + } + + mir::StatementKind::StorageDead(place) => { + stable_mir::mir::StatementKind::StorageDead(place.stable(tables)) + } + mir::StatementKind::Retag(retag, place) => { + stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables)) + } + mir::StatementKind::PlaceMention(place) => { + stable_mir::mir::StatementKind::PlaceMention(place.stable(tables)) } - PlaceMention(place) => stable_mir::mir::Statement::PlaceMention(place.stable(tables)), - AscribeUserType(place_projection, variance) => { - stable_mir::mir::Statement::AscribeUserType { + mir::StatementKind::AscribeUserType(place_projection, variance) => { + stable_mir::mir::StatementKind::AscribeUserType { place: place_projection.as_ref().0.stable(tables), projections: place_projection.as_ref().1.stable(tables), variance: variance.stable(tables), } } - Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)), - Intrinsic(intrinstic) => { - stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables)) + mir::StatementKind::Coverage(coverage) => { + stable_mir::mir::StatementKind::Coverage(opaque(coverage)) } - ConstEvalCounter => stable_mir::mir::Statement::ConstEvalCounter, - Nop => stable_mir::mir::Statement::Nop, + mir::StatementKind::Intrinsic(intrinstic) => { + stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables)) + } + mir::StatementKind::ConstEvalCounter => { + stable_mir::mir::StatementKind::ConstEvalCounter + } + mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, } } } @@ -276,7 +315,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { place.stable(tables), ), ThreadLocalRef(def_id) => { - stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id)) + stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) } AddressOf(mutability, place) => { stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables)) @@ -539,14 +578,14 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { } } -impl<'tcx> Stable<'tcx> for mir::Constant<'tcx> { +impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> { type T = stable_mir::mir::Constant; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { stable_mir::mir::Constant { span: self.span.stable(tables), user_ty: self.user_ty.map(|u| u.as_usize()).or(None), - literal: self.literal.stable(tables), + literal: self.const_.stable(tables), } } } @@ -739,7 +778,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple, mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => { stable_mir::mir::AggregateKind::Adt( - rustc_internal::adt_def(*def_id), + tables.adt_def(*def_id), var_idx.index(), generic_arg.stable(tables), user_ty_index.map(|idx| idx.index()), @@ -748,13 +787,13 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { } mir::AggregateKind::Closure(def_id, generic_arg) => { stable_mir::mir::AggregateKind::Closure( - rustc_internal::closure_def(*def_id), + tables.closure_def(*def_id), generic_arg.stable(tables), ) } mir::AggregateKind::Generator(def_id, generic_arg, movability) => { stable_mir::mir::AggregateKind::Generator( - rustc_internal::generator_def(*def_id), + tables.generator_def(*def_id), generic_arg.stable(tables), movability.stable(tables), ) @@ -804,11 +843,20 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { type T = stable_mir::mir::Terminator; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::TerminatorKind::*; use stable_mir::mir::Terminator; - match &self.kind { - Goto { target } => Terminator::Goto { target: target.as_usize() }, - SwitchInt { discr, targets } => Terminator::SwitchInt { + Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { + type T = stable_mir::mir::TerminatorKind; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::mir::TerminatorKind; + match self { + mir::TerminatorKind::Goto { target } => { + TerminatorKind::Goto { target: target.as_usize() } + } + mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt { discr: discr.stable(tables), targets: targets .iter() @@ -819,42 +867,60 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { .collect(), otherwise: targets.otherwise().as_usize(), }, - UnwindResume => Terminator::Resume, - UnwindTerminate(_) => Terminator::Abort, - Return => Terminator::Return, - Unreachable => Terminator::Unreachable, - Drop { place, target, unwind, replace: _ } => Terminator::Drop { - place: place.stable(tables), - target: target.as_usize(), - unwind: unwind.stable(tables), - }, - Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => { - Terminator::Call { - func: func.stable(tables), - args: args.iter().map(|arg| arg.stable(tables)).collect(), - destination: destination.stable(tables), - target: target.map(|t| t.as_usize()), + mir::TerminatorKind::UnwindResume => TerminatorKind::Resume, + mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort, + mir::TerminatorKind::Return => TerminatorKind::Return, + mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable, + mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => { + TerminatorKind::Drop { + place: place.stable(tables), + target: target.as_usize(), unwind: unwind.stable(tables), } } - Assert { cond, expected, msg, target, unwind } => Terminator::Assert { - cond: cond.stable(tables), - expected: *expected, - msg: msg.stable(tables), - target: target.as_usize(), + mir::TerminatorKind::Call { + func, + args, + destination, + target, + unwind, + call_source: _, + fn_span: _, + } => TerminatorKind::Call { + func: func.stable(tables), + args: args.iter().map(|arg| arg.stable(tables)).collect(), + destination: destination.stable(tables), + target: target.map(|t| t.as_usize()), unwind: unwind.stable(tables), }, - InlineAsm { template, operands, options, line_spans, destination, unwind } => { - Terminator::InlineAsm { - template: format!("{template:?}"), - operands: operands.iter().map(|operand| operand.stable(tables)).collect(), - options: format!("{options:?}"), - line_spans: format!("{line_spans:?}"), - destination: destination.map(|d| d.as_usize()), + mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => { + TerminatorKind::Assert { + cond: cond.stable(tables), + expected: *expected, + msg: msg.stable(tables), + target: target.as_usize(), unwind: unwind.stable(tables), } } - Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(), + mir::TerminatorKind::InlineAsm { + template, + operands, + options, + line_spans, + destination, + unwind, + } => TerminatorKind::InlineAsm { + template: format!("{template:?}"), + operands: operands.iter().map(|operand| operand.stable(tables)).collect(), + options: format!("{options:?}"), + line_spans: format!("{line_spans:?}"), + destination: destination.map(|d| d.as_usize()), + unwind: unwind.stable(tables), + }, + mir::TerminatorKind::Yield { .. } + | mir::TerminatorKind::GeneratorDrop + | mir::TerminatorKind::FalseEdge { .. } + | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(), } } } @@ -964,13 +1030,13 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Stable<'tcx> for ty::BoundTyKind { type T = stable_mir::ty::BoundTyKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::BoundTyKind; match self { ty::BoundTyKind::Anon => BoundTyKind::Anon, ty::BoundTyKind::Param(def_id, symbol) => { - BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string()) + BoundTyKind::Param(tables.param_def(*def_id), symbol.to_string()) } } } @@ -983,11 +1049,9 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { use stable_mir::ty::BoundRegionKind; match self { - ty::BoundRegionKind::BrAnon(option_span) => { - BoundRegionKind::BrAnon(option_span.map(|span| span.stable(tables))) - } + ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon, ty::BoundRegionKind::BrNamed(def_id, symbol) => { - BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string()) + BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string()) } ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv, } @@ -1074,12 +1138,10 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))), ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))), ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( - rustc_internal::adt_def(adt_def.did()), + tables.adt_def(adt_def.did()), generic_args.stable(tables), )), - ty::Foreign(def_id) => { - TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id))) - } + ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))), ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), constant.stable(tables))) @@ -1093,10 +1155,9 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { tables.intern_ty(*ty), mutbl.stable(tables), )), - ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( - rustc_internal::fn_def(*def_id), - generic_args.stable(tables), - )), + ty::FnDef(def_id, generic_args) => { + TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables))) + } ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))), ty::Dynamic(existential_predicates, region, dyn_kind) => { TyKind::RigidTy(RigidTy::Dynamic( @@ -1109,11 +1170,11 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { )) } ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( - rustc_internal::closure_def(*def_id), + tables.closure_def(*def_id), generic_args.stable(tables), )), ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( - rustc_internal::generator_def(*def_id), + tables.generator_def(*def_id), generic_args.stable(tables), movability.stable(tables), )), @@ -1128,11 +1189,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { ty::Bound(debruijn_idx, bound_ty) => { TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables)) } - ty::Placeholder(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(_, _) - | ty::Infer(_) - | ty::Error(_) => { + ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => { unreachable!(); } } @@ -1229,7 +1286,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { use stable_mir::ty::TraitDecl; TraitDecl { - def_id: rustc_internal::trait_def(self.def_id), + def_id: tables.trait_def(self.def_id), unsafety: self.unsafety.stable(tables), paren_sugar: self.paren_sugar, has_auto_impl: self.has_auto_impl, @@ -1247,13 +1304,13 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { } } -impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { +impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { type T = stable_mir::ty::Const; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { match *self { - ConstantKind::Ty(c) => c.stable(tables), - ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const { + mir::Const::Ty(c) => c.stable(tables), + mir::Const::Unevaluated(unev_const, ty) => stable_mir::ty::Const { literal: stable_mir::ty::ConstantKind::Unevaluated( stable_mir::ty::UnevaluatedConst { def: tables.const_def(unev_const.def), @@ -1263,7 +1320,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { ), ty: tables.intern_ty(ty), }, - ConstantKind::Val(val, ty) => stable_mir::ty::Const { + mir::Const::Val(val, ty) => stable_mir::ty::Const { literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( ty, val, tables, )), @@ -1278,7 +1335,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::TraitRef; - TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) } + TraitRef { def_id: tables.trait_def(self.def_id), args: self.args.stable(tables) } } } @@ -1508,9 +1565,39 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity { impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { type T = stable_mir::ty::Region; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - // FIXME: add a real implementation of stable regions - opaque(self) + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + Region { kind: self.kind().stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { + type T = stable_mir::ty::RegionKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::RegionKind; + match self { + ty::ReEarlyBound(early_reg) => RegionKind::ReEarlyBound(EarlyBoundRegion { + def_id: tables.region_def(early_reg.def_id), + index: early_reg.index, + name: early_reg.name.to_string(), + }), + ty::ReLateBound(db_index, bound_reg) => RegionKind::ReLateBound( + db_index.as_u32(), + BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) }, + ), + ty::ReStatic => RegionKind::ReStatic, + ty::RePlaceholder(place_holder) => { + RegionKind::RePlaceholder(stable_mir::ty::Placeholder { + universe: place_holder.universe.as_u32(), + bound: BoundRegion { + var: place_holder.bound.var.as_u32(), + kind: place_holder.bound.kind.stable(tables), + }, + }) + } + ty::ReErased => RegionKind::ReErased, + _ => unreachable!("{self:?}"), + } } } @@ -1522,8 +1609,11 @@ impl<'tcx> Stable<'tcx> for rustc_span::Span { } } -impl From for CompilerError { - fn from(_error: ErrorGuaranteed) -> Self { - CompilerError::CompilationFailed +impl<'tcx> Stable<'tcx> for DefKind { + type T = stable_mir::DefKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable DefKind + opaque(self) } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 68724c480376a..6fd61e45fcc9c 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -33,7 +33,7 @@ extern crate rustc_macros; #[macro_use] extern crate tracing; -use rustc_data_structures::{cold_path, AtomicRef}; +use rustc_data_structures::{outline, AtomicRef}; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -280,8 +280,7 @@ impl RealFileName { } /// Differentiates between real files and common virtual files. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)] -#[derive(Decodable, Encodable)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)] pub enum FileName { Real(RealFileName), /// Call to `quote!`. @@ -292,8 +291,6 @@ pub enum FileName { // FIXME(jseyfried) MacroExpansion(Hash64), ProcMacroSourceCode(Hash64), - /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`. - CfgSpec(Hash64), /// Strings provided as crate attributes in the CLI. CliCrateAttr(Hash64), /// Custom sources for explicit parser calls from plugins and drivers. @@ -305,7 +302,6 @@ pub enum FileName { impl From for FileName { fn from(p: PathBuf) -> Self { - assert!(!p.to_string_lossy().ends_with('>')); FileName::Real(RealFileName::LocalPath(p)) } } @@ -339,7 +335,6 @@ impl fmt::Display for FileNameDisplay<'_> { MacroExpansion(_) => write!(fmt, ""), Anon(_) => write!(fmt, ""), ProcMacroSourceCode(_) => write!(fmt, ""), - CfgSpec(_) => write!(fmt, ""), CliCrateAttr(_) => write!(fmt, ""), Custom(ref s) => write!(fmt, "<{s}>"), DocTest(ref path, _) => write!(fmt, "{}", path.display()), @@ -365,7 +360,6 @@ impl FileName { Anon(_) | MacroExpansion(_) | ProcMacroSourceCode(_) - | CfgSpec(_) | CliCrateAttr(_) | Custom(_) | QuoteExpansion(_) @@ -1592,7 +1586,7 @@ impl SourceFile { return &lines[..]; } - cold_path(|| { + outline(|| { self.convert_diffs_to_lines_frozen(); if let Some(SourceFileLines::Lines(lines)) = self.lines.get() { return &lines[..]; @@ -1753,7 +1747,7 @@ impl SourceFile { // is recorded. let diff = match self.normalized_pos.binary_search_by(|np| np.pos.cmp(&pos)) { Ok(i) => self.normalized_pos[i].diff, - Err(i) if i == 0 => 0, + Err(0) => 0, Err(i) => self.normalized_pos[i - 1].diff, }; @@ -1775,7 +1769,7 @@ impl SourceFile { .binary_search_by(|np| (np.pos.0 + np.diff).cmp(&(self.start_pos.0 + offset))) { Ok(i) => self.normalized_pos[i].diff, - Err(i) if i == 0 => 0, + Err(0) => 0, Err(i) => self.normalized_pos[i - 1].diff, }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 382754be2ca83..a62fa246ac41a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -129,9 +129,11 @@ symbols! { Alignment, Any, Arc, + ArcWeak, Argument, ArgumentMethods, Arguments, + ArrayIntoIter, AsMut, AsRef, AssertParamIsClone, @@ -164,6 +166,7 @@ symbols! { Capture, Center, Clone, + Command, ConstParamTy, Context, Continue, @@ -171,6 +174,7 @@ symbols! { Count, Cow, Debug, + DebugStruct, Decodable, Decoder, DecorateLint, @@ -194,6 +198,8 @@ symbols! { From, FromIterator, FromResidual, + FsOpenOptions, + FsPermissions, Future, FutureOutput, FxHashMap, @@ -207,16 +213,22 @@ symbols! { Implied, IndexOutput, Input, + Instant, Into, IntoDiagnostic, IntoFuture, IntoIterator, + IoLines, IoRead, + IoSeek, IoWrite, IpAddr, IrTyKind, Is, ItemContext, + IterEmpty, + IterOnce, + IterPeekable, Iterator, IteratorItem, Layout, @@ -227,6 +239,7 @@ symbols! { Mutex, MutexGuard, N, + NonNull, NonZeroI128, NonZeroI16, NonZeroI32, @@ -259,15 +272,19 @@ symbols! { ProcMacro, ProceduralMasqueradeDummyType, Range, + RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Rc, + RcWeak, Ready, Receiver, RefCell, + RefCellRef, + RefCellRefMut, Relaxed, Release, Result, @@ -284,6 +301,7 @@ symbols! { Send, SeqCst, SliceIndex, + SliceIter, Some, String, StructuralEq, @@ -561,6 +579,7 @@ symbols! { constant, constructor, context, + convert_identity, copy, copy_closures, copy_nonoverlapping, @@ -616,6 +635,7 @@ symbols! { declare_lint_pass, decode, default_alloc_error_handler, + default_fn, default_lib_allocator, default_method_body_is_const, default_type_parameter_fallback, @@ -628,6 +648,7 @@ symbols! { deref, deref_method, deref_mut, + deref_mut_method, deref_target, derive, derive_const, @@ -777,11 +798,14 @@ symbols! { from_desugaring, from_fn, from_iter, + from_iter_fn, from_output, from_residual, from_size_align_unchecked, + from_str_method, from_usize, from_yeet, + fs_create_dir, fsub_fast, fundamental, future, @@ -868,6 +892,10 @@ symbols! { into_iter, intra_doc_pointers, intrinsics, + intrinsics_unaligned_volatile_load, + intrinsics_unaligned_volatile_store, + io_stderr, + io_stdout, irrefutable_let_patterns, isa_attribute, isize, @@ -962,6 +990,7 @@ symbols! { mem_replace, mem_size_of, mem_size_of_val, + mem_swap, mem_uninitialized, mem_variant_count, mem_zeroed, @@ -1091,6 +1120,7 @@ symbols! { options, or, or_patterns, + ord_cmp_method, other, out, overflow_checks, @@ -1104,7 +1134,6 @@ symbols! { panic_abort, panic_bounds_check, panic_cannot_unwind, - panic_display, panic_fmt, panic_handler, panic_impl, @@ -1172,6 +1201,7 @@ symbols! { proc_macro_mod, proc_macro_non_items, proc_macro_path_invoc, + process_exit, profiler_builtins, profiler_runtime, ptr, @@ -1179,6 +1209,10 @@ symbols! { ptr_cast_const, ptr_cast_mut, ptr_const_is_null, + ptr_copy, + ptr_copy_nonoverlapping, + ptr_drop_in_place, + ptr_eq, ptr_from_ref, ptr_guaranteed_cmp, ptr_is_null, @@ -1187,8 +1221,17 @@ symbols! { ptr_null_mut, ptr_offset_from, ptr_offset_from_unsigned, + ptr_read, + ptr_read_unaligned, + ptr_read_volatile, + ptr_replace, + ptr_slice_from_raw_parts, + ptr_slice_from_raw_parts_mut, + ptr_swap, + ptr_swap_nonoverlapping, ptr_unique, ptr_write, + ptr_write_bytes, ptr_write_unaligned, ptr_write_volatile, pub_macro_rules, @@ -1299,6 +1342,7 @@ symbols! { rustc_coherence_is_core, rustc_coinductive, rustc_confusables, + rustc_const_panic_str, rustc_const_stable, rustc_const_unstable, rustc_conversion_suggestion, @@ -1465,6 +1509,7 @@ symbols! { simd_shl, simd_shr, simd_shuffle, + simd_shuffle_generic, simd_sub, simd_trunc, simd_xor, @@ -1477,6 +1522,8 @@ symbols! { sized, skip, slice, + slice_from_raw_parts, + slice_from_raw_parts_mut, slice_len_fn, slice_patterns, slicing_syntax, @@ -1564,7 +1611,9 @@ symbols! { thumb2, thumb_mode: "thumb-mode", tmm_reg, + to_owned_method, to_string, + to_string_method, to_vec, todo_macro, tool_attributes, @@ -1587,6 +1636,7 @@ symbols! { try_blocks, try_capture, try_from, + try_from_fn, try_into, try_trait_v2, tt, 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 77457c8daaa1f..6ad3e7155e825 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 @@ -118,7 +118,7 @@ fn encode_const<'tcx>( // bool value false is encoded as 0 and true as 1. match c.ty().kind() { ty::Int(ity) => { - let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty()); + let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { s.push('n'); @@ -126,7 +126,7 @@ fn encode_const<'tcx>( let _ = write!(s, "{val}"); } ty::Uint(_) => { - let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty()); + let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all()); let _ = write!(s, "{val}"); } ty::Bool => { @@ -720,7 +720,6 @@ fn encode_ty<'tcx>( | ty::Bound(..) | ty::Error(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Infer(..) | ty::Placeholder(..) => { bug!("encode_ty: unexpected `{:?}`", ty.kind()); @@ -973,12 +972,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ); } - ty::Bound(..) - | ty::Error(..) - | ty::GeneratorWitnessMIR(..) - | ty::Infer(..) - | ty::Param(..) - | ty::Placeholder(..) => { + ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => { bug!("transform_ty: unexpected `{:?}`", ty.kind()); } } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 2550570af65bc..82b1a772e3d7b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -329,7 +329,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon(_) }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + var.as_u32(); @@ -484,8 +484,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"), ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"), - ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"), - ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"), + ty::GeneratorWitness(..) => bug!("symbol_names: unexpected `GeneratorWitness`"), } // Only cache types that do not refer to an enclosing @@ -594,7 +593,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { self = ty.print(self)?; - let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ty); + let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all()); // Negative integer values are mangled using `n` as a "sign prefix". if let ty::Int(ity) = ty.kind() { diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 393e59e8b007e..a91eb41b18aeb 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -14,6 +14,7 @@ rustc_feature = { path = "../rustc_feature" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +rustc_index = { path = "../rustc_index" } [dependencies.object] version = "0.32.0" diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 74fe98920c459..f6f8b53d130b5 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::intern::Interned; pub use Integer::*; pub use Primitive::*; @@ -18,6 +19,111 @@ impl ToJson for Endian { } } +rustc_index::newtype_index! { + /// The *source-order* index of a field in a variant. + /// + /// This is how most code after type checking refers to fields, rather than + /// using names (as names have hygiene complications and more complex lookup). + /// + /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order. + /// (It is for `repr(C)` `struct`s, however.) + /// + /// For example, in the following types, + /// ```rust + /// # enum Never {} + /// # #[repr(u16)] + /// enum Demo1 { + /// Variant0 { a: Never, b: i32 } = 100, + /// Variant1 { c: u8, d: u64 } = 10, + /// } + /// struct Demo2 { e: u8, f: u16, g: u8 } + /// ``` + /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, + /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and + /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. + #[derive(HashStable_Generic)] + pub struct FieldIdx {} +} + +rustc_index::newtype_index! { + /// The *source-order* index of a variant in a type. + /// + /// For enums, these are always `0..variant_count`, regardless of any + /// custom discriminants that may have been defined, and including any + /// variants that may end up uninhabited due to field types. (Some of the + /// variants may not be present in a monomorphized ABI [`Variants`], but + /// those skipped variants are always counted when determining the *index*.) + /// + /// `struct`s, `tuples`, and `unions`s are considered to have a single variant + /// with variant index zero, aka [`FIRST_VARIANT`]. + #[derive(HashStable_Generic)] + pub struct VariantIdx { + /// Equivalent to `VariantIdx(0)`. + const FIRST_VARIANT = 0; + } +} +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] +#[rustc_pass_by_value] +pub struct Layout<'a>(pub Interned<'a, LayoutS>); + +impl<'a> fmt::Debug for Layout<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // See comment on `::fmt` above. + self.0.0.fmt(f) + } +} + +impl<'a> Deref for Layout<'a> { + type Target = &'a LayoutS; + fn deref(&self) -> &&'a LayoutS { + &self.0.0 + } +} + +impl<'a> Layout<'a> { + pub fn fields(self) -> &'a FieldsShape { + &self.0.0.fields + } + + pub fn variants(self) -> &'a Variants { + &self.0.0.variants + } + + pub fn abi(self) -> Abi { + self.0.0.abi + } + + pub fn largest_niche(self) -> Option { + self.0.0.largest_niche + } + + pub fn align(self) -> AbiAndPrefAlign { + self.0.0.align + } + + pub fn size(self) -> Size { + self.0.0.size + } + + pub fn max_repr_align(self) -> Option { + self.0.0.max_repr_align + } + + pub fn unadjusted_abi_align(self) -> Align { + self.0.0.unadjusted_abi_align + } + + /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. + /// + /// Currently, that means that the type is pointer-sized, pointer-aligned, + /// and has a scalar ABI. + pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { + self.size() == data_layout.pointer_size + && self.align().abi == data_layout.pointer_align.abi + && matches!(self.abi(), Abi::Scalar(..)) + } +} + /// The layout of a type, alongside the type itself. /// Provides various type traversal APIs (e.g., recursing into fields). /// @@ -42,8 +148,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> { } impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { - type Target = &'a LayoutS; - fn deref(&self) -> &&'a LayoutS { + type Target = &'a LayoutS; + fn deref(&self) -> &&'a LayoutS { &self.layout.0.0 } } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index f7dcec307ddd0..7a666eea437d9 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -11,7 +11,6 @@ use Arch::*; #[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub enum Arch { - Armv7, Armv7k, Armv7s, Arm64, @@ -29,7 +28,6 @@ pub enum Arch { impl Arch { pub fn target_name(self) -> &'static str { match self { - Armv7 => "armv7", Armv7k => "armv7k", Armv7s => "armv7s", Arm64 | Arm64_macabi | Arm64_sim => "arm64", @@ -43,7 +41,7 @@ impl Arch { pub fn target_arch(self) -> Cow<'static, str> { Cow::Borrowed(match self { - Armv7 | Armv7k | Armv7s => "arm", + Armv7k | Armv7s => "arm", Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", I386 | I686 => "x86", X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64", @@ -52,7 +50,7 @@ impl Arch { fn target_abi(self) -> &'static str { match self { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "", + Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "", X86_64_macabi | Arm64_macabi => "macabi", // x86_64-apple-ios is a simulator target, even though it isn't // declared that way in the target like the other ones... @@ -62,18 +60,20 @@ impl Arch { fn target_cpu(self) -> &'static str { match self { - Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher Armv7k => "cortex-a8", - Armv7s => "cortex-a9", + Armv7s => "swift", // iOS 10 is only supported on iPhone 5 or higher. Arm64 => "apple-a7", Arm64_32 => "apple-s4", - I386 | I686 => "yonah", - X86_64 | X86_64_sim => "core2", + // Only macOS 10.12+ is supported, which means + // all x86_64/x86 CPUs must be running at least penryn + // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82 + I386 | I686 => "penryn", + X86_64 | X86_64_sim => "penryn", + X86_64_macabi => "penryn", // Note: `core-avx2` is slightly more advanced than `x86_64h`, see // comments (and disabled features) in `x86_64h_apple_darwin` for - // details. + // details. It is a higher baseline then `penryn` however. X86_64h => "core-avx2", - X86_64_macabi => "core2", Arm64_macabi => "apple-a12", Arm64_sim => "apple-a12", } @@ -115,21 +115,6 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { } pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { - // Static TLS is only available in macOS 10.7+. If you try to compile for 10.6 - // either the linker will complain if it is used or the binary will end up - // segfaulting at runtime when run on 10.6. Rust by default supports macOS - // 10.7+, but there is a standard environment variable, - // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older - // versions of macOS. For example compiling on 10.10 with - // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate - // warnings about the usage of static TLS. - // - // Here we detect what version is being requested, defaulting to 10.7. Static - // TLS is flagged as enabled if it looks to be supported. The architecture - // only matters for default deployment target which is 11.0 for ARM64 and - // 10.7 for everything else. - let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7); - let abi = arch.target_abi(); TargetOptions { @@ -145,12 +130,17 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { pre_link_args: pre_link_args(os, arch, abi), families: cvs!["unix"], is_like_osx: true, - default_dwarf_version: 2, + // LLVM notes that macOS 10.11+ and iOS 9+ default + // to v4, so we do the same. + // https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203 + default_dwarf_version: 4, frame_pointer: FramePointer::Always, has_rpath: true, dll_suffix: ".dylib".into(), archive_format: "darwin".into(), - has_thread_local, + // Thread locals became available with iOS 8 and macOS 10.7, + // and both are far below our minimum. + has_thread_local: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, @@ -239,9 +229,7 @@ fn macos_default_deployment_target(arch: Arch) -> (u32, u32) { match arch { // Note: Arm64_sim is not included since macOS has no simulator. Arm64 | Arm64_macabi => (11, 0), - // x86_64h-apple-darwin only supports macOS 10.8 and later - X86_64h => (10, 8), - _ => (10, 7), + _ => (10, 12), } } @@ -292,8 +280,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow]> // Otherwise if cross-compiling for a different OS/SDK, remove any part // of the linking environment that's wrong and reversed. match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim - | X86_64h | Arm64_sim => { + Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim | X86_64h + | Arm64_sim => { cvs!["MACOSX_DEPLOYMENT_TARGET"] } X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], @@ -303,7 +291,7 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow]> fn ios_deployment_target() -> (u32, u32) { // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) + from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((10, 0)) } fn mac_catalyst_deployment_target() -> (u32, u32) { @@ -334,7 +322,7 @@ pub fn ios_sim_llvm_target(arch: Arch) -> String { fn tvos_deployment_target() -> (u32, u32) { // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) + from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0)) } fn tvos_lld_platform_version() -> String { diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs deleted file mode 100644 index 3259c854791ce..0000000000000 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::apple_base::{ios_llvm_target, opts, Arch}; -use crate::spec::{Target, TargetOptions}; - -pub fn target() -> Target { - let arch = Arch::Armv7; - Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - llvm_target: ios_llvm_target(arch).into(), - pointer_width: 32, - data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: arch.target_arch(), - options: TargetOptions { - features: "+v7,+vfp3,+neon".into(), - max_atomic_width: Some(64), - ..opts("ios", arch) - }, - } -} diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index be4bc6758443e..be7f8542c9e57 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -1,10 +1,10 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Armv7s; Target { - llvm_target: "armv7s-apple-ios".into(), + llvm_target: ios_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), arch: arch.target_arch(), diff --git a/compiler/rustc_target/src/spec/hurd_base.rs b/compiler/rustc_target/src/spec/hurd_base.rs new file mode 100644 index 0000000000000..76f8223c0e4ed --- /dev/null +++ b/compiler/rustc_target/src/spec/hurd_base.rs @@ -0,0 +1,15 @@ +use crate::spec::{cvs, RelroLevel, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + os: "hurd".into(), + dynamic_linking: true, + families: cvs!["unix"], + has_rpath: true, + position_independent_executables: true, + relro_level: RelroLevel::Full, + has_thread_local: true, + crt_static_respected: true, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/hurd_gnu_base.rs b/compiler/rustc_target/src/spec/hurd_gnu_base.rs new file mode 100644 index 0000000000000..b9cf26d9380bb --- /dev/null +++ b/compiler/rustc_target/src/spec/hurd_gnu_base.rs @@ -0,0 +1,5 @@ +use crate::spec::TargetOptions; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".into(), ..super::hurd_base::opts() } +} diff --git a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs new file mode 100644 index 0000000000000..29f8036013815 --- /dev/null +++ b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs @@ -0,0 +1,19 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; + +pub fn target() -> Target { + let mut base = super::hurd_gnu_base::opts(); + base.cpu = "pentiumpro".into(); + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); + base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) }; + + Target { + llvm_target: "i686-unknown-hurd-gnu".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ + f64:32:64-f80:32-n8:16:32-S128" + .into(), + arch: "x86".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8aa72797a0d25..d4774386e2ed2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -71,6 +71,8 @@ mod freebsd_base; mod fuchsia_base; mod haiku_base; mod hermit_base; +mod hurd_base; +mod hurd_gnu_base; mod illumos_base; mod l4re_base; mod linux_base; @@ -182,8 +184,6 @@ pub enum LinkerFlavorCli { Ld, Lld(LldFlavor), Em, - BpfLinker, - PtxLinker, } impl LinkerFlavorCli { @@ -197,9 +197,7 @@ impl LinkerFlavorCli { | LinkerFlavorCli::Msvc(Lld::Yes) | LinkerFlavorCli::EmCc | LinkerFlavorCli::Bpf - | LinkerFlavorCli::Ptx - | LinkerFlavorCli::BpfLinker - | LinkerFlavorCli::PtxLinker => true, + | LinkerFlavorCli::Ptx => true, LinkerFlavorCli::Gcc | LinkerFlavorCli::Ld | LinkerFlavorCli::Lld(..) @@ -277,8 +275,6 @@ impl LinkerFlavor { LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No), LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes), LinkerFlavorCli::Em => LinkerFlavor::EmCc, - LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf, - LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx, } } @@ -297,8 +293,8 @@ impl LinkerFlavor { LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link), LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No), LinkerFlavor::EmCc => LinkerFlavorCli::Em, - LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker, - LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker, + LinkerFlavor::Bpf => LinkerFlavorCli::Bpf, + LinkerFlavor::Ptx => LinkerFlavorCli::Ptx, } } @@ -318,7 +314,6 @@ impl LinkerFlavor { LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)), LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)), LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)), - LinkerFlavorCli::BpfLinker | LinkerFlavorCli::PtxLinker => (None, None), } } @@ -517,8 +512,6 @@ linker_flavor_cli_impls! { (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link" (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld" (LinkerFlavorCli::Em) "em" - (LinkerFlavorCli::BpfLinker) "bpf-linker" - (LinkerFlavorCli::PtxLinker) "ptx-linker" } impl ToJson for LinkerFlavorCli { @@ -1367,6 +1360,8 @@ supported_targets! { ("i686-unknown-haiku", i686_unknown_haiku), ("x86_64-unknown-haiku", x86_64_unknown_haiku), + ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu), + ("aarch64-apple-darwin", aarch64_apple_darwin), ("x86_64-apple-darwin", x86_64_apple_darwin), ("x86_64h-apple-darwin", x86_64h_apple_darwin), @@ -1390,7 +1385,6 @@ supported_targets! { ("i386-apple-ios", i386_apple_ios), ("x86_64-apple-ios", x86_64_apple_ios), ("aarch64-apple-ios", aarch64_apple_ios), - ("armv7-apple-ios", armv7_apple_ios), ("armv7s-apple-ios", armv7s_apple_ios), ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi), ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi), diff --git a/compiler/rustc_target/src/spec/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/riscv64_linux_android.rs index af0d685549414..91f5e562d8b86 100644 --- a/compiler/rustc_target/src/spec/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/riscv64_linux_android.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { code_model: Some(CodeModel::Medium), cpu: "generic-rv64".into(), - features: "+m,+a,+f,+d,+c".into(), + features: "+m,+a,+f,+d,+c,+Zba,+Zbb,+Zbs".into(), llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs index 8d80fcd5fe579..624837a22d60f 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs @@ -3,7 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target if is for the Android v7a ABI in thumb mode with // NEON unconditionally enabled and, therefore, with 32 FPU registers // enabled as well. See section A2.6.2 on page A2-56 in -// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf +// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf // See https://developer.android.com/ndk/guides/abis.html#v7a // for target ABI requirements. diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs index 28c81340ad899..b500c50de9850 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions}; // (for consistency with Android and Debian-based distributions) // and with NEON unconditionally enabled and, therefore, with 32 FPU // registers enabled as well. See section A2.6.2 on page A2-56 in -// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf +// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs index 2c375ab22d795..dce0cbcef0268 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions}; // (for consistency with Android and Debian-based distributions) // and with NEON unconditionally enabled and, therefore, with 32 FPU // registers enabled as well. See section A2.6.2 on page A2-56 in -// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf +// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs index 8968d3c8fc100..a50a55ad7e028 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs @@ -46,6 +46,7 @@ pub fn opts() -> TargetOptions { stack_probes: StackProbeType::Call, singlethread: true, linker: Some("rust-lld".into()), + entry_name: "efi_main".into(), ..base } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index e90bda9c9a871..e3f5d7321d133 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -5,7 +5,7 @@ use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64; let mut base = opts("macos", arch); - base.max_atomic_width = Some(128); // core2 supports cmpxchg16b + base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs index 67664a74710a3..41ba768068a35 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs @@ -5,13 +5,14 @@ // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::spec::Target; +use crate::{abi::call::Conv, spec::Target}; pub fn target() -> Target { let mut base = super::uefi_msvc_base::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); + base.entry_abi = Conv::X86_64Win64; // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to // enable these CPU features explicitly before their first use, otherwise their instructions diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 128b9ad7e472b..23d2c0c4ea095 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -469,7 +469,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // FIXME: These should ideally not exist as a self type. It would be nice for // the builtin auto trait impls of generators to instead directly recurse // into the witness. - ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(_, _) => (), + ty::GeneratorWitness(..) => (), // These variants should not exist as a self type. ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) @@ -621,8 +621,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Dynamic(..) | ty::Closure(..) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Param(_) @@ -778,8 +777,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Alias(..) | ty::Closure(..) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Param(_) 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 b61e02ba76106..26c68acddffef 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -61,9 +61,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()]) } - ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()), - - ty::GeneratorWitnessMIR(def_id, args) => Ok(ecx + ty::GeneratorWitness(def_id, args) => Ok(ecx .tcx() .generator_hidden_types(def_id) .map(|bty| { @@ -96,8 +94,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( let mut counter = 0; let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { ty::ReErased => { - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon }; counter += 1; ty::Region::new_late_bound(tcx, current_depth, br) } @@ -105,7 +102,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( r => bug!("unexpected region: {r:?}"), }); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))), + (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)), ); ty::Binder::bind_with_vars(ty, bound_vars) } @@ -127,7 +124,6 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -204,9 +200,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } } - ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()), - - ty::GeneratorWitnessMIR(def_id, args) => Ok(ecx + ty::GeneratorWitness(def_id, args) => Ok(ecx .tcx() .generator_hidden_types(def_id) .map(|bty| { @@ -282,8 +276,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( | ty::Ref(_, _, _) | ty::Dynamic(_, _, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Alias(_, _) diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index f5901057a9dcf..aa92b924ef2e5 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -269,7 +269,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { self.primitive_var_infos.push(CanonicalVarInfo { kind }); var }); - let br = ty::BoundRegion { var, kind: BrAnon(None) }; + let br = ty::BoundRegion { var, kind: BrAnon }; ty::Region::new_late_bound(self.interner(), self.binder_index, br) } @@ -330,8 +330,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Alias(_, _) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 7941f64873b62..066129d8e4731 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -344,7 +344,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, ) -> Result<(bool, Certainty, Vec>>), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); - let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, goal_evaluation_kind); + let mut goal_evaluation = + self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); let encountered_overflow = self.search_graph.encountered_overflow(); let canonical_response = EvalCtxt::evaluate_canonical_goal( self.tcx(), @@ -568,7 +569,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes }, unconstrained_goal, )?; - self.add_goals(instantiate_goals); + self.nested_goals.goals.extend(instantiate_goals); // Finally, equate the goal's RHS with the unconstrained var. // We put the nested goals from this into goals instead of @@ -605,7 +606,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::No }, goal, )?; - self.add_goals(instantiate_goals); + self.nested_goals.goals.extend(instantiate_goals); if has_changed { unchanged_certainty = None; } @@ -613,7 +614,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { match certainty { Certainty::Yes => {} Certainty::Maybe(_) => { - self.add_goal(goal); + self.nested_goals.goals.push(goal); unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty)); } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 790f9b840f2b0..b3f9218d7619c 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -10,17 +10,21 @@ //! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html use super::{CanonicalInput, Certainty, EvalCtxt, Goal}; use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; -use crate::solve::{response_no_constraints_raw, CanonicalResponse, QueryResult, Response}; +use crate::solve::{ + inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response, +}; use rustc_data_structures::fx::FxHashSet; use rustc_index::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; -use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; +use rustc_middle::infer::canonical::Canonical; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{ ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput, }; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, @@ -29,6 +33,22 @@ use rustc_span::DUMMY_SP; use std::iter; use std::ops::Deref; +trait ResponseT<'tcx> { + fn var_values(&self) -> CanonicalVarValues<'tcx>; +} + +impl<'tcx> ResponseT<'tcx> for Response<'tcx> { + fn var_values(&self) -> CanonicalVarValues<'tcx> { + self.var_values + } +} + +impl<'tcx, T> ResponseT<'tcx> for inspect::State<'tcx, T> { + fn var_values(&self) -> CanonicalVarValues<'tcx> { + self.var_values + } +} + impl<'tcx> EvalCtxt<'_, 'tcx> { /// Canonicalizes the goal remembering the original values /// for each bound variable. @@ -188,12 +208,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { original_values: Vec>, response: CanonicalResponse<'tcx>, ) -> Result<(Certainty, Vec>>), NoSolution> { - let substitution = self.compute_query_response_substitution(&original_values, &response); + let substitution = + Self::compute_query_response_substitution(self.infcx, &original_values, &response); let Response { var_values, external_constraints, certainty } = response.substitute(self.tcx(), &substitution); - let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?; + let nested_goals = + Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values)?; let ExternalConstraintsData { region_constraints, opaque_types } = external_constraints.deref(); @@ -206,21 +228,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// This returns the substitutions to instantiate the bound variables of /// the canonical response. This depends on the `original_values` for the /// bound variables. - fn compute_query_response_substitution( - &self, + fn compute_query_response_substitution>( + infcx: &InferCtxt<'tcx>, original_values: &[ty::GenericArg<'tcx>], - response: &CanonicalResponse<'tcx>, + response: &Canonical<'tcx, T>, ) -> CanonicalVarValues<'tcx> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. - let prev_universe = self.infcx.universe(); + let prev_universe = infcx.universe(); let universes_created_in_query = response.max_universe.index(); for _ in 0..universes_created_in_query { - self.infcx.create_next_universe(); + infcx.create_next_universe(); } - let var_values = response.value.var_values; + let var_values = response.value.var_values(); assert_eq!(original_values.len(), var_values.len()); // If the query did not make progress with constraining inference variables, @@ -254,13 +276,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - let var_values = self.tcx().mk_args_from_iter(response.variables.iter().enumerate().map( + let var_values = infcx.tcx.mk_args_from_iter(response.variables.iter().enumerate().map( |(index, info)| { if info.universe() != ty::UniverseIndex::ROOT { // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| { + infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -274,7 +296,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let Some(v) = opt_values[BoundVar::from_usize(index)] { v } else { - self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) + infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this @@ -287,9 +309,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { CanonicalVarValues { var_values } } - #[instrument(level = "debug", skip(self, param_env), ret)] + #[instrument(level = "debug", skip(infcx, param_env), ret)] fn unify_query_var_values( - &self, + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, original_values: &[ty::GenericArg<'tcx>], var_values: CanonicalVarValues<'tcx>, @@ -298,7 +320,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let mut nested_goals = vec![]; for (&orig, response) in iter::zip(original_values, var_values.var_values) { - nested_goals.extend(self.eq_and_get_goals(param_env, orig, response)?); + nested_goals.extend( + infcx + .at(&ObligationCause::dummy(), param_env) + .eq(DefineOpaqueTypes::No, orig, response) + .map(|InferOk { value: (), obligations }| { + obligations.into_iter().map(|o| Goal::from(o)) + }) + .map_err(|e| { + debug!(?e, "failed to equate"); + NoSolution + })?, + ); } Ok(nested_goals) @@ -403,3 +436,35 @@ impl<'tcx> TypeFolder> for EagerResolver<'_, 'tcx> { } } } + +impl<'tcx> inspect::ProofTreeBuilder<'tcx> { + pub fn make_canonical_state>>( + ecx: &EvalCtxt<'_, 'tcx>, + data: T, + ) -> inspect::CanonicalState<'tcx, T> { + let state = inspect::State { var_values: ecx.var_values, data }; + let state = state.fold_with(&mut EagerResolver { infcx: ecx.infcx }); + Canonicalizer::canonicalize( + ecx.infcx, + CanonicalizeMode::Response { max_input_universe: ecx.max_input_universe }, + &mut vec![], + state, + ) + } + + pub fn instantiate_canonical_state>>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + original_values: &[ty::GenericArg<'tcx>], + state: inspect::CanonicalState<'tcx, T>, + ) -> Result<(Vec>>, T), NoSolution> { + let substitution = + EvalCtxt::compute_query_response_substitution(infcx, original_values, &state); + + let inspect::State { var_values, data } = state.substitute(infcx.tcx, &substitution); + + let nested_goals = + EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values)?; + Ok((nested_goals, data)) + } +} diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs new file mode 100644 index 0000000000000..15c8d9e5bcb02 --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -0,0 +1,235 @@ +/// An infrastructure to mechanically analyse proof trees. +/// +/// It is unavoidable that this representation is somewhat +/// lossy as it should hide quite a few semantically relevant things, +/// e.g. canonicalization and the order of nested goals. +/// +/// @lcnr: However, a lot of the weirdness here is not strictly necessary +/// and could be improved in the future. This is mostly good enough for +/// coherence right now and was annoying to implement, so I am leaving it +/// as is until we start using it for something else. +use std::ops::ControlFlow; + +use rustc_infer::infer::InferCtxt; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::{inspect, QueryResult}; +use rustc_middle::traits::solve::{Certainty, Goal}; +use rustc_middle::ty; + +use crate::solve::inspect::ProofTreeBuilder; +use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache}; + +pub struct InspectGoal<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, + depth: usize, + orig_values: &'a [ty::GenericArg<'tcx>], + goal: Goal<'tcx, ty::Predicate<'tcx>>, + evaluation: &'a inspect::GoalEvaluation<'tcx>, +} + +pub struct InspectCandidate<'a, 'tcx> { + goal: &'a InspectGoal<'a, 'tcx>, + kind: inspect::ProbeKind<'tcx>, + nested_goals: Vec>>>, + result: QueryResult<'tcx>, +} + +impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { + pub fn infcx(&self) -> &'a InferCtxt<'tcx> { + self.goal.infcx + } + + pub fn kind(&self) -> inspect::ProbeKind<'tcx> { + self.kind + } + + pub fn result(&self) -> Result { + self.result.map(|c| c.value.certainty) + } + + /// Visit the nested goals of this candidate. + /// + /// FIXME(@lcnr): we have to slightly adapt this API + /// to also use it to compute the most relevant goal + /// for fulfillment errors. Will do that once we actually + /// need it. + pub fn visit_nested>( + &self, + visitor: &mut V, + ) -> ControlFlow { + // HACK: An arbitrary cutoff to avoid dealing with overflow and cycles. + if self.goal.depth >= 10 { + let infcx = self.goal.infcx; + infcx.probe(|_| { + let mut instantiated_goals = vec![]; + for goal in &self.nested_goals { + let goal = match ProofTreeBuilder::instantiate_canonical_state( + infcx, + self.goal.goal.param_env, + self.goal.orig_values, + *goal, + ) { + Ok((_goals, goal)) => goal, + Err(NoSolution) => { + warn!( + "unexpected failure when instantiating {:?}: {:?}", + goal, self.nested_goals + ); + return ControlFlow::Continue(()); + } + }; + instantiated_goals.push(goal); + } + + for &goal in &instantiated_goals { + let (_, proof_tree) = + infcx.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No)); + let proof_tree = proof_tree.unwrap(); + visitor.visit_goal(&InspectGoal::new( + infcx, + self.goal.depth + 1, + &proof_tree, + ))?; + } + + ControlFlow::Continue(()) + })?; + } + ControlFlow::Continue(()) + } +} + +impl<'a, 'tcx> InspectGoal<'a, 'tcx> { + pub fn infcx(&self) -> &'a InferCtxt<'tcx> { + self.infcx + } + + pub fn goal(&self) -> Goal<'tcx, ty::Predicate<'tcx>> { + self.goal + } + + pub fn result(&self) -> Result { + self.evaluation.evaluation.result.map(|c| c.value.certainty) + } + + fn candidates_recur( + &'a self, + candidates: &mut Vec>, + nested_goals: &mut Vec>>>, + probe: &inspect::Probe<'tcx>, + ) { + for step in &probe.steps { + match step { + &inspect::ProbeStep::AddGoal(goal) => nested_goals.push(goal), + inspect::ProbeStep::EvaluateGoals(_) => (), + inspect::ProbeStep::NestedProbe(ref probe) => { + // Nested probes have to prove goals added in their parent + // but do not leak them, so we truncate the added goals + // afterwards. + let num_goals = nested_goals.len(); + self.candidates_recur(candidates, nested_goals, probe); + nested_goals.truncate(num_goals); + } + } + } + + match probe.kind { + inspect::ProbeKind::NormalizedSelfTyAssembly + | inspect::ProbeKind::UnsizeAssembly + | inspect::ProbeKind::UpcastProjectionCompatibility => (), + // We add a candidate for the root evaluation if there + // is only one way to prove a given goal, e.g. for `WellFormed`. + // + // FIXME: This is currently wrong if we don't even try any + // candidates, e.g. for a trait goal, as in this case `candidates` is + // actually supposed to be empty. + inspect::ProbeKind::Root { result } => { + if candidates.is_empty() { + candidates.push(InspectCandidate { + goal: self, + kind: probe.kind, + nested_goals: nested_goals.clone(), + result, + }); + } + } + inspect::ProbeKind::MiscCandidate { name: _, result } + | inspect::ProbeKind::TraitCandidate { source: _, result } => { + candidates.push(InspectCandidate { + goal: self, + kind: probe.kind, + nested_goals: nested_goals.clone(), + result, + }); + } + } + } + + pub fn candidates(&'a self) -> Vec> { + let mut candidates = vec![]; + let last_eval_step = match self.evaluation.evaluation.kind { + inspect::CanonicalGoalEvaluationKind::Overflow + | inspect::CanonicalGoalEvaluationKind::CacheHit(_) => { + warn!("unexpected root evaluation: {:?}", self.evaluation); + return vec![]; + } + inspect::CanonicalGoalEvaluationKind::Uncached { ref revisions } => { + if let Some(last) = revisions.last() { + last + } else { + return vec![]; + } + } + }; + + let mut nested_goals = vec![]; + self.candidates_recur(&mut candidates, &mut nested_goals, &last_eval_step.evaluation); + + candidates + } + + fn new( + infcx: &'a InferCtxt<'tcx>, + depth: usize, + root: &'a inspect::GoalEvaluation<'tcx>, + ) -> Self { + match root.kind { + inspect::GoalEvaluationKind::Root { ref orig_values } => InspectGoal { + infcx, + depth, + orig_values, + goal: infcx.resolve_vars_if_possible(root.uncanonicalized_goal), + evaluation: root, + }, + inspect::GoalEvaluationKind::Nested { .. } => unreachable!(), + } + } +} + +/// The public API to interact with proof trees. +pub trait ProofTreeVisitor<'tcx> { + type BreakTy; + + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; +} + +pub trait ProofTreeInferCtxtExt<'tcx> { + fn visit_proof_tree>( + &self, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + visitor: &mut V, + ) -> ControlFlow; +} + +impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { + fn visit_proof_tree>( + &self, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + visitor: &mut V, + ) -> ControlFlow { + let (_, proof_tree) = + self.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No)); + let proof_tree = proof_tree.unwrap(); + visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + } +} diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs similarity index 76% rename from compiler/rustc_trait_selection/src/solve/inspect.rs rename to compiler/rustc_trait_selection/src/solve/inspect/build.rs index 749bba33c9b67..2eba98b02e907 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -1,28 +1,107 @@ +//! Building proof trees incrementally during trait solving. +//! +//! This code is *a bit* of a mess and can hopefully be +//! mostly ignored. For a general overview of how it works, +//! see the comment on [ProofTreeBuilder]. use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::solve::inspect::{self, CacheHit, ProbeKind}; use rustc_middle::traits::solve::{ CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult, }; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::DumpSolverProofTree; -use super::eval_ctxt::UseGlobalCache; -use super::{GenerateProofTree, GoalEvaluationKind}; +use crate::solve::eval_ctxt::UseGlobalCache; +use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree}; + +/// The core data structure when building proof trees. +/// +/// In case the current evaluation does not generate a proof +/// tree, `state` is simply `None` and we avoid any work. +/// +/// The possible states of the solver are represented via +/// variants of [DebugSolver]. For any nested computation we call +/// `ProofTreeBuilder::new_nested_computation_kind` which +/// creates a new `ProofTreeBuilder` to temporarily replace the +/// current one. Once that nested computation is done, +/// `ProofTreeBuilder::nested_computation_kind` is called +/// to add the finished nested evaluation to the parent. +/// +/// We provide additional information to the current state +/// by calling methods such as `ProofTreeBuilder::probe_kind`. +/// +/// The actual structure closely mirrors the finished proof +/// trees. At the end of trait solving `ProofTreeBuilder::finalize` +/// is called to recursively convert the whole structure to a +/// finished proof tree. +pub(in crate::solve) struct ProofTreeBuilder<'tcx> { + state: Option>>, +} + +struct BuilderData<'tcx> { + tree: DebugSolver<'tcx>, + use_global_cache: UseGlobalCache, +} + +/// The current state of the proof tree builder, at most places +/// in the code, only one or two variants are actually possible. +/// +/// We simply ICE in case that assumption is broken. +#[derive(Debug)] +enum DebugSolver<'tcx> { + Root, + GoalEvaluation(WipGoalEvaluation<'tcx>), + CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<'tcx>), + AddedGoalsEvaluation(WipAddedGoalsEvaluation<'tcx>), + GoalEvaluationStep(WipGoalEvaluationStep<'tcx>), + Probe(WipProbe<'tcx>), +} + +impl<'tcx> From> for DebugSolver<'tcx> { + fn from(g: WipGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::GoalEvaluation(g) + } +} + +impl<'tcx> From> for DebugSolver<'tcx> { + fn from(g: WipCanonicalGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::CanonicalGoalEvaluation(g) + } +} + +impl<'tcx> From> for DebugSolver<'tcx> { + fn from(g: WipAddedGoalsEvaluation<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::AddedGoalsEvaluation(g) + } +} + +impl<'tcx> From> for DebugSolver<'tcx> { + fn from(g: WipGoalEvaluationStep<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::GoalEvaluationStep(g) + } +} + +impl<'tcx> From> for DebugSolver<'tcx> { + fn from(p: WipProbe<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::Probe(p) + } +} #[derive(Eq, PartialEq, Debug)] -pub struct WipGoalEvaluation<'tcx> { +struct WipGoalEvaluation<'tcx> { pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, - pub kind: WipGoalEvaluationKind, + pub kind: WipGoalEvaluationKind<'tcx>, pub evaluation: Option>, pub returned_goals: Vec>>, } impl<'tcx> WipGoalEvaluation<'tcx> { - pub fn finalize(self) -> inspect::GoalEvaluation<'tcx> { + fn finalize(self) -> inspect::GoalEvaluation<'tcx> { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, kind: match self.kind { - WipGoalEvaluationKind::Root => inspect::GoalEvaluationKind::Root, + WipGoalEvaluationKind::Root { orig_values } => { + inspect::GoalEvaluationKind::Root { orig_values } + } WipGoalEvaluationKind::Nested { is_normalizes_to_hack } => { inspect::GoalEvaluationKind::Nested { is_normalizes_to_hack } } @@ -34,27 +113,27 @@ impl<'tcx> WipGoalEvaluation<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub enum WipGoalEvaluationKind { - Root, +pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> { + Root { orig_values: Vec> }, Nested { is_normalizes_to_hack: IsNormalizesToHack }, } #[derive(Eq, PartialEq, Debug)] -pub enum WipCanonicalGoalEvaluationKind { +pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { Overflow, - CacheHit(CacheHit), + CacheHit(inspect::CacheHit), } #[derive(Eq, PartialEq, Debug)] -pub struct WipCanonicalGoalEvaluation<'tcx> { - pub goal: CanonicalInput<'tcx>, - pub kind: Option, - pub revisions: Vec>, - pub result: Option>, +struct WipCanonicalGoalEvaluation<'tcx> { + goal: CanonicalInput<'tcx>, + kind: Option, + revisions: Vec>, + result: Option>, } impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { - pub fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> { + fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> { let kind = match self.kind { Some(WipCanonicalGoalEvaluationKind::Overflow) => { inspect::CanonicalGoalEvaluationKind::Overflow @@ -76,13 +155,13 @@ impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub struct WipAddedGoalsEvaluation<'tcx> { - pub evaluations: Vec>>, - pub result: Option>, +struct WipAddedGoalsEvaluation<'tcx> { + evaluations: Vec>>, + result: Option>, } impl<'tcx> WipAddedGoalsEvaluation<'tcx> { - pub fn finalize(self) -> inspect::AddedGoalsEvaluation<'tcx> { + fn finalize(self) -> inspect::AddedGoalsEvaluation<'tcx> { inspect::AddedGoalsEvaluation { evaluations: self .evaluations @@ -97,17 +176,17 @@ impl<'tcx> WipAddedGoalsEvaluation<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub struct WipGoalEvaluationStep<'tcx> { - pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, +struct WipGoalEvaluationStep<'tcx> { + instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, - pub evaluation: WipProbe<'tcx>, + evaluation: WipProbe<'tcx>, } impl<'tcx> WipGoalEvaluationStep<'tcx> { - pub fn finalize(self) -> inspect::GoalEvaluationStep<'tcx> { + fn finalize(self) -> inspect::GoalEvaluationStep<'tcx> { let evaluation = self.evaluation.finalize(); match evaluation.kind { - ProbeKind::Root { .. } => (), + inspect::ProbeKind::Root { .. } => (), _ => unreachable!("unexpected root evaluation: {evaluation:?}"), } inspect::GoalEvaluationStep { instantiated_goal: self.instantiated_goal, evaluation } @@ -115,13 +194,13 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub struct WipProbe<'tcx> { +struct WipProbe<'tcx> { pub steps: Vec>, - pub kind: Option>, + pub kind: Option>, } impl<'tcx> WipProbe<'tcx> { - pub fn finalize(self) -> inspect::Probe<'tcx> { + fn finalize(self) -> inspect::Probe<'tcx> { inspect::Probe { steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(), kind: self.kind.unwrap(), @@ -130,14 +209,14 @@ impl<'tcx> WipProbe<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub enum WipProbeStep<'tcx> { - AddGoal(Goal<'tcx, ty::Predicate<'tcx>>), +enum WipProbeStep<'tcx> { + AddGoal(inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>), EvaluateGoals(WipAddedGoalsEvaluation<'tcx>), NestedProbe(WipProbe<'tcx>), } impl<'tcx> WipProbeStep<'tcx> { - pub fn finalize(self) -> inspect::ProbeStep<'tcx> { + fn finalize(self) -> inspect::ProbeStep<'tcx> { match self { WipProbeStep::AddGoal(goal) => inspect::ProbeStep::AddGoal(goal), WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), @@ -146,55 +225,6 @@ impl<'tcx> WipProbeStep<'tcx> { } } -#[derive(Debug)] -pub enum DebugSolver<'tcx> { - Root, - GoalEvaluation(WipGoalEvaluation<'tcx>), - CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<'tcx>), - AddedGoalsEvaluation(WipAddedGoalsEvaluation<'tcx>), - GoalEvaluationStep(WipGoalEvaluationStep<'tcx>), - Probe(WipProbe<'tcx>), -} - -impl<'tcx> From> for DebugSolver<'tcx> { - fn from(g: WipGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::GoalEvaluation(g) - } -} - -impl<'tcx> From> for DebugSolver<'tcx> { - fn from(g: WipCanonicalGoalEvaluation<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::CanonicalGoalEvaluation(g) - } -} - -impl<'tcx> From> for DebugSolver<'tcx> { - fn from(g: WipAddedGoalsEvaluation<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::AddedGoalsEvaluation(g) - } -} - -impl<'tcx> From> for DebugSolver<'tcx> { - fn from(g: WipGoalEvaluationStep<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::GoalEvaluationStep(g) - } -} - -impl<'tcx> From> for DebugSolver<'tcx> { - fn from(p: WipProbe<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::Probe(p) - } -} - -pub struct ProofTreeBuilder<'tcx> { - state: Option>>, -} - -struct BuilderData<'tcx> { - tree: DebugSolver<'tcx>, - use_global_cache: UseGlobalCache, -} - impl<'tcx> ProofTreeBuilder<'tcx> { fn new( state: impl Into>, @@ -273,16 +303,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> { self.state.is_none() } - pub(super) fn new_goal_evaluation( + pub(in crate::solve) fn new_goal_evaluation( &mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>, - kind: GoalEvaluationKind, + orig_values: &[ty::GenericArg<'tcx>], + kind: solve::GoalEvaluationKind, ) -> ProofTreeBuilder<'tcx> { self.nested(|| WipGoalEvaluation { uncanonicalized_goal: goal, kind: match kind { - GoalEvaluationKind::Root => WipGoalEvaluationKind::Root, - GoalEvaluationKind::Nested { is_normalizes_to_hack } => { + solve::GoalEvaluationKind::Root => { + WipGoalEvaluationKind::Root { orig_values: orig_values.to_vec() } + } + solve::GoalEvaluationKind::Nested { is_normalizes_to_hack } => { WipGoalEvaluationKind::Nested { is_normalizes_to_hack } } }, @@ -379,7 +412,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { self.nested(|| WipProbe { steps: vec![], kind: None }) } - pub fn probe_kind(&mut self, probe_kind: ProbeKind<'tcx>) { + pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<'tcx>) { if let Some(this) = self.as_mut() { match this { DebugSolver::Probe(this) => { @@ -390,18 +423,22 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn add_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) { - if let Some(this) = self.as_mut() { - match this { - DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { - evaluation: WipProbe { steps, .. }, - .. - }) - | DebugSolver::Probe(WipProbe { steps, .. }) => { - steps.push(WipProbeStep::AddGoal(goal)) - } - _ => unreachable!(), - } + pub fn add_goal(ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, ty::Predicate<'tcx>>) { + // Can't use `if let Some(this) = ecx.inspect.as_mut()` here because + // we have to immutably use the `EvalCtxt` for `make_canonical_state`. + if ecx.inspect.is_noop() { + return; + } + + let goal = Self::make_canonical_state(ecx, goal); + + match ecx.inspect.as_mut().unwrap() { + DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { + evaluation: WipProbe { steps, .. }, + .. + }) + | DebugSolver::Probe(WipProbe { steps, .. }) => steps.push(WipProbeStep::AddGoal(goal)), + s => unreachable!("tried to add {goal:?} to {s:?}"), } } @@ -471,7 +508,10 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } DebugSolver::GoalEvaluationStep(evaluation_step) => { assert_eq!( - evaluation_step.evaluation.kind.replace(ProbeKind::Root { result }), + evaluation_step + .evaluation + .kind + .replace(inspect::ProbeKind::Root { result }), None ); } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs new file mode 100644 index 0000000000000..60d52305a6be4 --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs @@ -0,0 +1,7 @@ +pub use rustc_middle::traits::solve::inspect::*; + +mod build; +pub(in crate::solve) use build::*; + +mod analyse; +pub use analyse::*; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index bd612ce4778db..77a3b5e128457 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -235,7 +235,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self))] fn add_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) { - self.inspect.add_goal(goal); + inspect::ProofTreeBuilder::add_goal(self, goal); self.nested_goals.goals.push(goal); } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index f6e781b87ba7f..339a3e738467c 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -59,7 +59,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } DefKind::AnonConst => self.normalize_anon_const(goal), DefKind::OpaqueTy => self.normalize_opaque_type(goal), - DefKind::TyAlias { .. } => self.normalize_weak_type(goal), + DefKind::TyAlias => self.normalize_weak_type(goal), kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), } } @@ -346,14 +346,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) }); - let pred = ty::Clause::from_projection_clause( - tcx, - tupled_inputs_and_output.map_bound(|(inputs, output)| ty::ProjectionPredicate { + let pred = tupled_inputs_and_output + .map_bound(|(inputs, output)| ty::ProjectionPredicate { projection_ty: tcx .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]), term: output.into(), - }), - ); + }) + .to_predicate(tcx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -388,7 +387,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Foreign(..) => tcx.types.unit, @@ -556,7 +554,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Foreign(..) | ty::Adt(_, _) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs deleted file mode 100644 index be48447e27c24..0000000000000 --- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! This module both handles the global cache which stores "finished" goals, -//! and the provisional cache which contains partially computed goals. -//! -//! The provisional cache is necessary when dealing with coinductive cycles. -//! -//! For more information about the provisional cache and coinduction in general, -//! check out the relevant section of the rustc-dev-guide. -//! -//! FIXME(@lcnr): Write that section, feel free to ping me if you need help here -//! before then or if I still haven't done that before January 2023. -use super::StackDepth; -use rustc_data_structures::fx::FxHashMap; -use rustc_index::IndexVec; -use rustc_middle::traits::solve::{CanonicalInput, QueryResult}; - -rustc_index::newtype_index! { - pub struct EntryIndex {} -} - -#[derive(Debug, Clone)] -pub(super) struct ProvisionalEntry<'tcx> { - /// In case we have a coinductive cycle, this is the - /// the current provisional result of this goal. - /// - /// This starts out as `None` for all goals and gets to some - /// when the goal gets popped from the stack or we rerun evaluation - /// for this goal to reach a fixpoint. - pub(super) response: Option>, - /// In case of a cycle, the position of deepest stack entry involved - /// in that cycle. This is monotonically decreasing in the stack as all - /// elements between the current stack element in the deepest stack entry - /// involved have to also be involved in that cycle. - /// - /// We can only move entries to the global cache once we're complete done - /// with the cycle. If this entry has not been involved in a cycle, - /// this is just its own depth. - pub(super) depth: StackDepth, - - /// The goal for this entry. Should always be equal to the corresponding goal - /// in the lookup table. - pub(super) input: CanonicalInput<'tcx>, -} - -pub(super) struct ProvisionalCache<'tcx> { - pub(super) entries: IndexVec>, - // FIXME: This is only used to quickly check whether a given goal - // is in the cache. We should experiment with using something like - // `SsoHashSet` here because in most cases there are only a few entries. - pub(super) lookup_table: FxHashMap, EntryIndex>, -} - -impl<'tcx> ProvisionalCache<'tcx> { - pub(super) fn empty() -> ProvisionalCache<'tcx> { - ProvisionalCache { entries: Default::default(), lookup_table: Default::default() } - } - - pub(super) fn is_empty(&self) -> bool { - self.entries.is_empty() && self.lookup_table.is_empty() - } - - /// Adds a dependency from the current leaf to `target` in the cache - /// to prevent us from moving any goals which depend on the current leaf - /// to the global cache while we're still computing `target`. - /// - /// Its important to note that `target` may already be part of a different cycle. - /// In this case we have to ensure that we also depend on all other goals - /// in the existing cycle in addition to the potentially direct cycle with `target`. - pub(super) fn add_dependency_of_leaf_on(&mut self, target: EntryIndex) { - let depth = self.entries[target].depth; - for provisional_entry in &mut self.entries.raw[target.index()..] { - // The depth of `target` is the position of the deepest goal in the stack - // on which `target` depends. That goal is the `root` of this cycle. - // - // Any entry which was added after `target` is either on the stack itself - // at which point its depth is definitely at least as high as the depth of - // `root`. If it's not on the stack itself it has to depend on a goal - // between `root` and `leaf`. If it were to depend on a goal deeper in the - // stack than `root`, then `root` would also depend on that goal, at which - // point `root` wouldn't be the root anymore. - debug_assert!(provisional_entry.depth >= depth); - provisional_entry.depth = depth; - } - - // We only update entries which were added after `target` as no other - // entry should have a higher depth. - // - // Any entry which previously had a higher depth than target has to - // be between `target` and `root`. Because of this we would have updated - // its depth when calling `add_dependency_of_leaf_on(root)` for `target`. - if cfg!(debug_assertions) { - self.entries.iter().all(|e| e.depth <= depth); - } - } - - pub(super) fn depth(&self, entry_index: EntryIndex) -> StackDepth { - self.entries[entry_index].depth - } - - pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> Option> { - self.entries[entry_index].response - } -} 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 16de518e8e0b0..33513f6bd439d 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -1,14 +1,11 @@ -mod cache; - -use self::cache::ProvisionalEntry; use super::inspect; use super::inspect::ProofTreeBuilder; use super::SolverMode; -use cache::ProvisionalCache; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_index::Idx; use rustc_index::IndexVec; -use rustc_middle::dep_graph::DepKind; +use rustc_middle::dep_graph::dep_kinds; use rustc_middle::traits::solve::inspect::CacheHit; use rustc_middle::traits::solve::CacheData; use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult}; @@ -27,8 +24,14 @@ struct StackEntry<'tcx> { // The maximum depth reached by this stack entry, only up-to date // for the top of the stack and lazily updated for the rest. reached_depth: StackDepth, + // In case of a cycle, the depth of the root. + cycle_root_depth: StackDepth, + encountered_overflow: bool, has_been_used: bool, + /// Starts out as `None` and gets set when rerunning this + /// goal in case we encounter a cycle. + provisional_result: Option>, /// We put only the root goal of a coinductive cycle into the global cache. /// @@ -47,7 +50,7 @@ pub(super) struct SearchGraph<'tcx> { /// /// An element is *deeper* in the stack if its index is *lower*. stack: IndexVec>, - provisional_cache: ProvisionalCache<'tcx>, + stack_entries: FxHashMap, StackDepth>, } impl<'tcx> SearchGraph<'tcx> { @@ -56,7 +59,7 @@ impl<'tcx> SearchGraph<'tcx> { mode, local_overflow_limit: tcx.recursion_limit().0.checked_ilog2().unwrap_or(0) as usize, stack: Default::default(), - provisional_cache: ProvisionalCache::empty(), + stack_entries: Default::default(), } } @@ -85,6 +88,7 @@ impl<'tcx> SearchGraph<'tcx> { /// would cause us to not track overflow and recursion depth correctly. fn pop_stack(&mut self) -> StackEntry<'tcx> { let elem = self.stack.pop().unwrap(); + assert!(self.stack_entries.remove(&elem.input).is_some()); if let Some(last) = self.stack.raw.last_mut() { last.reached_depth = last.reached_depth.max(elem.reached_depth); last.encountered_overflow |= elem.encountered_overflow; @@ -104,22 +108,17 @@ impl<'tcx> SearchGraph<'tcx> { } pub(super) fn is_empty(&self) -> bool { - self.stack.is_empty() && self.provisional_cache.is_empty() + self.stack.is_empty() } /// Whether we're currently in a cycle. This should only be used /// for debug assertions. pub(super) fn in_cycle(&self) -> bool { if let Some(stack_depth) = self.stack.last_index() { - // Either the current goal on the stack is the root of a cycle... - if self.stack[stack_depth].has_been_used { - return true; - } - - // ...or it depends on a goal with a lower depth. - let current_goal = self.stack[stack_depth].input; - let entry_index = self.provisional_cache.lookup_table[¤t_goal]; - self.provisional_cache.entries[entry_index].depth != stack_depth + // Either the current goal on the stack is the root of a cycle + // or it depends on a goal with a lower depth. + self.stack[stack_depth].has_been_used + || self.stack[stack_depth].cycle_root_depth != stack_depth } else { false } @@ -211,9 +210,8 @@ impl<'tcx> SearchGraph<'tcx> { } } - // Look at the provisional cache to detect cycles. - let cache = &mut self.provisional_cache; - match cache.lookup_table.entry(input) { + // Check whether we're in a cycle. + match self.stack_entries.entry(input) { // No entry, we push this goal on the stack and try to prove it. Entry::Vacant(v) => { let depth = self.stack.next_index(); @@ -221,14 +219,14 @@ impl<'tcx> SearchGraph<'tcx> { input, available_depth, reached_depth: depth, + cycle_root_depth: depth, encountered_overflow: false, has_been_used: false, + provisional_result: None, cycle_participants: Default::default(), }; assert_eq!(self.stack.push(entry), depth); - let entry_index = - cache.entries.push(ProvisionalEntry { response: None, depth, input }); - v.insert(entry_index); + v.insert(depth); } // We have a nested goal which relies on a goal `root` deeper in the stack. // @@ -239,41 +237,50 @@ impl<'tcx> SearchGraph<'tcx> { // // Finally we can return either the provisional response for that goal if we have a // coinductive cycle or an ambiguous result if the cycle is inductive. - Entry::Occupied(entry_index) => { + Entry::Occupied(entry) => { inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit( CacheHit::Provisional, )); - let entry_index = *entry_index.get(); - let stack_depth = cache.depth(entry_index); + let stack_depth = *entry.get(); debug!("encountered cycle with depth {stack_depth:?}"); - - cache.add_dependency_of_leaf_on(entry_index); - let mut iter = self.stack.iter_mut(); - let root = iter.nth(stack_depth.as_usize()).unwrap(); - for e in iter { - root.cycle_participants.insert(e.input); + // We start by updating the root depth of all cycle participants, and + // add all cycle participants to the root. + let root_depth = self.stack[stack_depth].cycle_root_depth; + let (prev, participants) = self.stack.raw.split_at_mut(stack_depth.as_usize() + 1); + let root = &mut prev[root_depth.as_usize()]; + for entry in participants { + debug_assert!(entry.cycle_root_depth >= root_depth); + entry.cycle_root_depth = root_depth; + root.cycle_participants.insert(entry.input); + // FIXME(@lcnr): I believe that this line is needed as we could + // otherwise access a cache entry for the root of a cycle while + // computing the result for a cycle participant. This can result + // in unstable results due to incompleteness. + // + // However, a test for this would be an even more complex version of + // tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs. + // I did not bother to write such a test and we have no regression test + // for this. It would be good to have such a test :) + #[allow(rustc::potential_query_instability)] + root.cycle_participants.extend(entry.cycle_participants.drain()); } - // If we're in a cycle, we have to retry proving the current goal - // until we reach a fixpoint. + // If we're in a cycle, we have to retry proving the cycle head + // until we reach a fixpoint. It is not enough to simply retry the + // `root` goal of this cycle. + // + // See tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs + // for an example. self.stack[stack_depth].has_been_used = true; - return if let Some(result) = cache.provisional_result(entry_index) { + return if let Some(result) = self.stack[stack_depth].provisional_result { result } else { - // If we don't have a provisional result yet, the goal has to - // still be on the stack. - let mut goal_on_stack = false; - let mut is_coinductive = true; - for entry in self.stack.raw[stack_depth.index()..] + // If we don't have a provisional result yet we're in the first iteration, + // so we start with no constraints. + let is_coinductive = self.stack.raw[stack_depth.index()..] .iter() - .skip_while(|entry| entry.input != input) - { - goal_on_stack = true; - is_coinductive &= entry.input.value.goal.predicate.is_coinductive(tcx); - } - debug_assert!(goal_on_stack); - + .all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx)); if is_coinductive { Self::response_no_constraints(tcx, input, Certainty::Yes) } else { @@ -287,47 +294,32 @@ impl<'tcx> SearchGraph<'tcx> { // Everything that affects the `result` should be performed within this // `with_anon_task` closure. let ((final_entry, result), dep_node) = - tcx.dep_graph.with_anon_task(tcx, DepKind::TraitSelect, || { + tcx.dep_graph.with_anon_task(tcx, dep_kinds::TraitSelect, || { // When we encounter a coinductive cycle, we have to fetch the // result of that cycle while we are still computing it. Because // of this we continuously recompute the cycle until the result // of the previous iteration is equal to the final result, at which // point we are done. for _ in 0..self.local_overflow_limit() { - let response = prove_goal(self, inspect); + let result = prove_goal(self, inspect); // Check whether the current goal is the root of a cycle and whether // we have to rerun because its provisional result differed from the // final result. - // - // Also update the response for this goal stored in the provisional - // cache. let stack_entry = self.pop_stack(); debug_assert_eq!(stack_entry.input, input); - let cache = &mut self.provisional_cache; - let provisional_entry_index = - *cache.lookup_table.get(&stack_entry.input).unwrap(); - let provisional_entry = &mut cache.entries[provisional_entry_index]; if stack_entry.has_been_used - && provisional_entry.response.map_or(true, |r| r != response) + && stack_entry.provisional_result.map_or(true, |r| r != result) { - // If so, update the provisional result for this goal and remove - // all entries whose result depends on this goal from the provisional - // cache... - // - // That's not completely correct, as a nested goal can also only - // depend on a goal which is lower in the stack so it doesn't - // actually depend on the current goal. This should be fairly - // rare and is hopefully not relevant for performance. - provisional_entry.response = Some(response); - #[allow(rustc::potential_query_instability)] - cache.lookup_table.retain(|_key, index| *index <= provisional_entry_index); - cache.entries.truncate(provisional_entry_index.index() + 1); - - // ...and finally push our goal back on the stack and reevaluate it. - self.stack.push(StackEntry { has_been_used: false, ..stack_entry }); + // If so, update its provisional result and reevaluate it. + let depth = self.stack.push(StackEntry { + has_been_used: false, + provisional_result: Some(result), + ..stack_entry + }); + assert_eq!(self.stack_entries.insert(input, depth), None); } else { - return (stack_entry, response); + return (stack_entry, result); } } @@ -343,17 +335,7 @@ impl<'tcx> SearchGraph<'tcx> { // // It is not possible for any nested goal to depend on something deeper on the // stack, as this would have also updated the depth of the current goal. - let cache = &mut self.provisional_cache; - let provisional_entry_index = *cache.lookup_table.get(&input).unwrap(); - let provisional_entry = &mut cache.entries[provisional_entry_index]; - let depth = provisional_entry.depth; - if depth == self.stack.next_index() { - for (i, entry) in cache.entries.drain_enumerated(provisional_entry_index.index()..) { - let actual_index = cache.lookup_table.remove(&entry.input); - debug_assert_eq!(Some(i), actual_index); - debug_assert!(entry.depth == depth); - } - + if final_entry.cycle_root_depth == self.stack.next_index() { // When encountering a cycle, both inductive and coinductive, we only // move the root into the global cache. We also store all other cycle // participants involved. @@ -371,8 +353,6 @@ impl<'tcx> SearchGraph<'tcx> { dep_node, result, ) - } else { - provisional_entry.response = Some(result); } result diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f18eed94a6844..8055c63b9f301 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -879,8 +879,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Closure(_, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(_, _) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Adt(_, _) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e90723b0ee80a..acab4498a0985 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,9 +6,15 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; +use crate::solve::inspect; +use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use crate::traits::engine::TraitEngineExt; use crate::traits::outlives_bounds::InferCtxtExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs}; +use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::util::impl_subject_and_oblig; +use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{ self, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, @@ -18,10 +24,13 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::util; +use rustc_infer::traits::{util, TraitEngine}; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE; @@ -31,9 +40,6 @@ 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 /// to some remote crate. #[derive(Copy, Clone, Debug)] @@ -205,19 +211,19 @@ fn overlap<'tcx>( // Equate the headers to find their intersection (the general type, with infer vars, // that may apply both impls). - let equate_obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?; + let mut obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); + obligations.extend( + [&impl1_header.predicates, &impl2_header.predicates].into_iter().flatten().map( + |&predicate| Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate), + ), + ); + if overlap_mode.use_implicit_negative() { for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] { if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| { - impl_intersection_has_impossible_obligation( - selcx, - param_env, - &impl1_header, - &impl2_header, - &equate_obligations, - ) + impl_intersection_has_impossible_obligation(selcx, &obligations) }) { if matches!(mode, TreatInductiveCycleAs::Recur) { let first_local_impl = impl1_header @@ -281,7 +287,14 @@ fn overlap<'tcx>( return None; } - let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); + let intercrate_ambiguity_causes = if !overlap_mode.use_implicit_negative() { + Default::default() + } else if infcx.next_trait_solver() { + compute_intercrate_ambiguity_causes(&infcx, &obligations) + } else { + selcx.take_intercrate_ambiguity_causes() + }; + debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); let involves_placeholder = infcx .inner @@ -335,34 +348,24 @@ fn equate_impl_headers<'tcx>( /// of the two impls above to be empty. /// /// Importantly, this works even if there isn't a `impl !Error for MyLocalType`. -fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( +fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - impl1_header: &ty::ImplHeader<'tcx>, - impl2_header: &ty::ImplHeader<'tcx>, - obligations: &PredicateObligations<'tcx>, -) -> Option> { + obligations: &'a [PredicateObligation<'tcx>], +) -> Option<&'a PredicateObligation<'tcx>> { let infcx = selcx.infcx; - [&impl1_header.predicates, &impl2_header.predicates] - .into_iter() - .flatten() - .map(|&predicate| { - Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) - }) - .chain(obligations.into_iter().cloned()) - .find(|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 cannot use 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(), - ) - } - }) + obligations.iter().find(|obligation| { + 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 cannot use 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(), + ) + } + }) } /// Check if both impls can be satisfied by a common type by considering whether @@ -824,9 +827,7 @@ where // This should only be created when checking whether we have to check whether some // auto trait impl applies. There will never be multiple impls, so we can just // act as if it were a local type here. - ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(..) => { - ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) - } + ty::GeneratorWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), ty::Alias(ty::Opaque, ..) => { // This merits some explanation. // Normally, opaque types are not involved when performing @@ -882,3 +883,144 @@ where ControlFlow::Continue(()) } } + +/// Compute the `intercrate_ambiguity_causes` for the new solver using +/// "proof trees". +/// +/// This is a bit scuffed but seems to be good enough, at least +/// when looking at UI tests. Given that it is only used to improve +/// diagnostics this is good enough. We can always improve it once there +/// are test cases where it is currently not enough. +fn compute_intercrate_ambiguity_causes<'tcx>( + infcx: &InferCtxt<'tcx>, + obligations: &[PredicateObligation<'tcx>], +) -> FxIndexSet { + let mut causes: FxIndexSet = Default::default(); + + for obligation in obligations { + search_ambiguity_causes(infcx, obligation.clone().into(), &mut causes); + } + + causes +} + +struct AmbiguityCausesVisitor<'a> { + causes: &'a mut FxIndexSet, +} + +impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> { + type BreakTy = !; + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow { + let infcx = goal.infcx(); + for cand in goal.candidates() { + cand.visit_nested(self)?; + } + // When searching for intercrate ambiguity causes, we only need to look + // at ambiguous goals, as for others the coherence unknowable candidate + // was irrelevant. + match goal.result() { + Ok(Certainty::Maybe(_)) => {} + Ok(Certainty::Yes) | Err(NoSolution) => return ControlFlow::Continue(()), + } + + let Goal { param_env, predicate } = goal.goal(); + + // For bound predicates we simply call `infcx.replace_bound_vars_with_placeholders` + // and then prove the resulting predicate as a nested goal. + let trait_ref = match predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, + Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) => { + proj.projection_ty.trait_ref(infcx.tcx) + } + _ => return ControlFlow::Continue(()), + }; + + let mut ambiguity_cause = None; + for cand in goal.candidates() { + // FIXME: boiiii, using string comparisions here sure is scuffed. + if let inspect::ProbeKind::MiscCandidate { name: "coherence unknowable", result: _ } = + cand.kind() + { + let lazily_normalize_ty = |ty: Ty<'tcx>| { + let mut fulfill_cx = >::new(infcx); + if matches!(ty.kind(), ty::Alias(..)) { + // FIXME(-Ztrait-solver=next-coherence): we currently don't + // normalize opaque types here, resulting in diverging behavior + // for TAITs. + match infcx + .at(&ObligationCause::dummy(), param_env) + .structurally_normalize(ty, &mut *fulfill_cx) + { + Ok(ty) => Ok(ty), + Err(_errs) => Err(()), + } + } else { + Ok(ty) + } + }; + + infcx.probe(|_| { + match trait_ref_is_knowable(infcx.tcx, trait_ref, lazily_normalize_ty) { + Err(()) => {} + Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"), + Ok(Err(conflict)) => { + if !trait_ref.references_error() { + let self_ty = trait_ref.self_ty(); + let (trait_desc, self_desc) = with_no_trimmed_paths!({ + let trait_desc = trait_ref.print_only_trait_path().to_string(); + let self_desc = self_ty + .has_concrete_skeleton() + .then(|| self_ty.to_string()); + (trait_desc, self_desc) + }); + ambiguity_cause = Some(match conflict { + Conflict::Upstream => { + IntercrateAmbiguityCause::UpstreamCrateUpdate { + trait_desc, + self_desc, + } + } + Conflict::Downstream => { + IntercrateAmbiguityCause::DownstreamCrate { + trait_desc, + self_desc, + } + } + }); + } + } + } + }) + } else { + match cand.result() { + // We only add an ambiguity cause if the goal would otherwise + // result in an error. + // + // FIXME: While this matches the behavior of the + // old solver, it is not the only way in which the unknowable + // candidates *weaken* coherence, they can also force otherwise + // sucessful normalization to be ambiguous. + Ok(Certainty::Maybe(_) | Certainty::Yes) => { + ambiguity_cause = None; + break; + } + Err(NoSolution) => continue, + } + } + } + + if let Some(ambiguity_cause) = ambiguity_cause { + self.causes.insert(ambiguity_cause); + } + + ControlFlow::Continue(()) + } +} + +fn search_ambiguity_causes<'tcx>( + infcx: &InferCtxt<'tcx>, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + causes: &mut FxIndexSet, +) { + infcx.visit_proof_tree(goal, &mut AmbiguityCausesVisitor { causes }); +} diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 820973dc090ad..88f47b03cc8df 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -23,6 +23,7 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::TraitSolver; @@ -156,6 +157,20 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + pub fn relate>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + variance: Variance, + expected: T, + actual: T, + ) -> Result<(), TypeError<'tcx>> { + self.infcx + .at(cause, param_env) + .relate(DefineOpaqueTypes::Yes, expected, variance, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + /// Checks whether `expected` is a supertype of `actual`: `expected :> actual`. pub fn sup>( &self, @@ -203,7 +218,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { def_id: LocalDefId, ) -> Result>, ErrorGuaranteed> { self.assumed_wf_types(param_env, def_id) - .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors)) + .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors)) } pub fn assumed_wf_types( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs new file mode 100644 index 0000000000000..b4835b011ddb7 --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -0,0 +1,275 @@ +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::InferCtxt; +use crate::traits::{Obligation, ObligationCause, ObligationCtxt}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_hir as hir; +use rustc_hir::Node; +use rustc_middle::ty::{self, Ty}; +use rustc_span::{Span, DUMMY_SP}; + +use super::ArgKind; + +pub use rustc_infer::traits::error_reporting::*; + +pub trait InferCtxtExt<'tcx> { + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)>; + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + closure_pipe_span: Option, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + + /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` + /// in that order, and returns the generic type corresponding to the + /// argument of that trait (corresponding to the closure arguments). + fn type_implements_fn_trait( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: ty::Binder<'tcx, Ty<'tcx>>, + polarity: ty::ImplPolarity, + ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; +} + +impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)> { + let sm = self.tcx.sess.source_map(); + let hir = self.tcx.hir(); + Some(match node { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), + .. + }) => ( + fn_decl_span, + fn_arg_span, + hir.body(body) + .params + .iter() + .map(|arg| { + if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = + *arg.pat + { + Some(ArgKind::Tuple( + Some(span), + args.iter() + .map(|pat| { + sm.span_to_snippet(pat.span) + .ok() + .map(|snippet| (snippet, "_".to_owned())) + }) + .collect::>>()?, + )) + } else { + let name = sm.span_to_snippet(arg.pat.span).ok()?; + Some(ArgKind::Arg(name, "_".to_owned())) + } + }) + .collect::>>()?, + ), + Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) + | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Fn(ref sig, _), .. + }) => ( + sig.span, + None, + sig.decl + .inputs + .iter() + .map(|arg| match arg.kind { + hir::TyKind::Tup(ref tys) => ArgKind::Tuple( + Some(arg.span), + vec![("_".to_owned(), "_".to_owned()); tys.len()], + ), + _ => ArgKind::empty(), + }) + .collect::>(), + ), + Node::Ctor(ref variant_data) => { + let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); + (span, None, vec![ArgKind::empty(); variant_data.fields().len()]) + } + _ => panic!("non-FnLike node found: {node:?}"), + }) + } + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + closure_arg_span: Option, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let kind = if is_closure { "closure" } else { "function" }; + + let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { + let arg_length = arguments.len(); + let distinct = matches!(other, &[ArgKind::Tuple(..)]); + match (arg_length, arguments.get(0)) { + (1, Some(ArgKind::Tuple(_, fields))) => { + format!("a single {}-tuple as argument", fields.len()) + } + _ => format!( + "{} {}argument{}", + arg_length, + if distinct && arg_length > 1 { "distinct " } else { "" }, + pluralize!(arg_length) + ), + } + }; + + let expected_str = args_str(&expected_args, &found_args); + let found_str = args_str(&found_args, &expected_args); + + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0593, + "{} is expected to take {}, but it takes {}", + kind, + expected_str, + found_str, + ); + + err.span_label(span, format!("expected {kind} that takes {expected_str}")); + + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {found_str}")); + + // Suggest to take and ignore the arguments with expected_args_length `_`s if + // found arguments is empty (assume the user just wants to ignore args in this case). + // For example, if `expected_args_length` is 2, suggest `|_, _|`. + if found_args.is_empty() && is_closure { + let underscores = vec!["_"; expected_args.len()].join(", "); + err.span_suggestion_verbose( + closure_arg_span.unwrap_or(found_span), + format!( + "consider changing the closure to take and ignore the expected argument{}", + pluralize!(expected_args.len()) + ), + format!("|{underscores}|"), + Applicability::MachineApplicable, + ); + } + + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields + .iter() + .map(|(name, _)| name.to_owned()) + .collect::>() + .join(", "); + err.span_suggestion_verbose( + found_span, + "change the closure to take multiple arguments instead of a single tuple", + format!("|{sugg}|"), + Applicability::MachineApplicable, + ); + } + } + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] + && fields.len() == found_args.len() + && is_closure + { + let sugg = format!( + "|({}){}|", + found_args + .iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!( + ": ({})", + fields + .iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ") + ) + } else { + String::new() + }, + ); + err.span_suggestion_verbose( + found_span, + "change the closure to accept a tuple instead of individual arguments", + sugg, + Applicability::MachineApplicable, + ); + } + } + + err + } + + fn type_implements_fn_trait( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: ty::Binder<'tcx, Ty<'tcx>>, + polarity: ty::ImplPolarity, + ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { + self.commit_if_ok(|_| { + for trait_def_id in [ + self.tcx.lang_items().fn_trait(), + self.tcx.lang_items().fn_mut_trait(), + self.tcx.lang_items().fn_once_trait(), + ] { + let Some(trait_def_id) = trait_def_id else { continue }; + // Make a fresh inference variable so we can determine what the substitutions + // of the trait are. + let var = self.next_ty_var(TypeVariableOrigin { + span: DUMMY_SP, + kind: TypeVariableOriginKind::MiscVariable, + }); + // FIXME(effects) + let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); + let obligation = Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty.rebind(ty::TraitPredicate { trait_ref, polarity }), + ); + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation); + if ocx.select_all_or_error().is_empty() { + return Ok(( + self.tcx + .fn_trait_kind_from_def_id(trait_def_id) + .expect("expected to map DefId to ClosureKind"), + ty.rebind(self.resolve_vars_if_possible(var)), + )); + } + } + + Err(()) + }) + } +} 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 7d754cbafa347..989c1310b76c8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1,56 +1,25 @@ +// ignore-tidy-filelength :( + mod ambiguity; +mod infer_ctxt_ext; pub mod on_unimplemented; pub mod suggestions; +mod type_err_ctxt_ext; -use super::{ - FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionError, TraitNotObjectSafe, -}; -use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch}; -use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{self, InferCtxt}; +use super::{Obligation, ObligationCause, ObligationCauseCode, PredicateObligation}; +use crate::infer::InferCtxt; use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache}; -use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::specialize::to_pretty_impl_header; -use crate::traits::NormalizeExt; -use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _}; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{ - pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, Style, -}; use rustc_hir as hir; -use rustc_hir::def::Namespace; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -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::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::{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::{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 rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; use std::io::Write; -use std::iter; use std::ops::ControlFlow; -use suggestions::TypeErrCtxtExt as _; +pub use self::infer_ctxt_ext::*; +pub use self::type_err_ctxt_ext::*; pub use rustc_infer::traits::error_reporting::*; // When outputting impl candidates, prefer showing those that are more similar. @@ -67,6 +36,7 @@ pub enum CandidateSimilarity { pub struct ImplCandidate<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub similarity: CandidateSimilarity, + impl_def_id: DefId, } enum GetSafeTransmuteErrorAndReason { @@ -74,3356 +44,8 @@ enum GetSafeTransmuteErrorAndReason { Error { err_msg: String, safe_transmute_explanation: String }, } -pub trait InferCtxtExt<'tcx> { - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)>; - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - closure_pipe_span: Option, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; - - /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` - /// in that order, and returns the generic type corresponding to the - /// argument of that trait (corresponding to the closure arguments). - fn type_implements_fn_trait( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: ty::Binder<'tcx, Ty<'tcx>>, - polarity: ty::ImplPolarity, - ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; -} - -pub trait TypeErrCtxtExt<'tcx> { - fn build_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> - where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; - - fn report_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - mutate: impl FnOnce(&mut Diagnostic), - ) -> ! - where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; - - fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; - - fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed; - - fn report_overflow_obligation( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: ToPredicate<'tcx> + Clone; - - fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); - - fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; - - /// The `root_obligation` parameter should be the `root_obligation` field - /// from a `FulfillmentError`. If no `FulfillmentError` is available, - /// then it should be the same as `obligation`. - fn report_selection_error( - &self, - obligation: PredicateObligation<'tcx>, - root_obligation: &PredicateObligation<'tcx>, - error: &SelectionError<'tcx>, - ); - - fn report_const_param_not_wf( - &self, - ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)> { - let sm = self.tcx.sess.source_map(); - let hir = self.tcx.hir(); - Some(match node { - Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), - .. - }) => ( - fn_decl_span, - fn_arg_span, - hir.body(body) - .params - .iter() - .map(|arg| { - if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = - *arg.pat - { - Some(ArgKind::Tuple( - Some(span), - args.iter() - .map(|pat| { - sm.span_to_snippet(pat.span) - .ok() - .map(|snippet| (snippet, "_".to_owned())) - }) - .collect::>>()?, - )) - } else { - let name = sm.span_to_snippet(arg.pat.span).ok()?; - Some(ArgKind::Arg(name, "_".to_owned())) - } - }) - .collect::>>()?, - ), - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) - | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Fn(ref sig, _), .. - }) => ( - sig.span, - None, - sig.decl - .inputs - .iter() - .map(|arg| match arg.kind { - hir::TyKind::Tup(ref tys) => ArgKind::Tuple( - Some(arg.span), - vec![("_".to_owned(), "_".to_owned()); tys.len()], - ), - _ => ArgKind::empty(), - }) - .collect::>(), - ), - Node::Ctor(ref variant_data) => { - let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); - (span, None, vec![ArgKind::empty(); variant_data.fields().len()]) - } - _ => panic!("non-FnLike node found: {node:?}"), - }) - } - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - closure_arg_span: Option, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let kind = if is_closure { "closure" } else { "function" }; - - let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { - let arg_length = arguments.len(); - let distinct = matches!(other, &[ArgKind::Tuple(..)]); - match (arg_length, arguments.get(0)) { - (1, Some(ArgKind::Tuple(_, fields))) => { - format!("a single {}-tuple as argument", fields.len()) - } - _ => format!( - "{} {}argument{}", - arg_length, - if distinct && arg_length > 1 { "distinct " } else { "" }, - pluralize!(arg_length) - ), - } - }; - - let expected_str = args_str(&expected_args, &found_args); - let found_str = args_str(&found_args, &expected_args); - - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0593, - "{} is expected to take {}, but it takes {}", - kind, - expected_str, - found_str, - ); - - err.span_label(span, format!("expected {kind} that takes {expected_str}")); - - if let Some(found_span) = found_span { - err.span_label(found_span, format!("takes {found_str}")); - - // Suggest to take and ignore the arguments with expected_args_length `_`s if - // found arguments is empty (assume the user just wants to ignore args in this case). - // For example, if `expected_args_length` is 2, suggest `|_, _|`. - if found_args.is_empty() && is_closure { - let underscores = vec!["_"; expected_args.len()].join(", "); - err.span_suggestion_verbose( - closure_arg_span.unwrap_or(found_span), - format!( - "consider changing the closure to take and ignore the expected argument{}", - pluralize!(expected_args.len()) - ), - format!("|{underscores}|"), - Applicability::MachineApplicable, - ); - } - - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields - .iter() - .map(|(name, _)| name.to_owned()) - .collect::>() - .join(", "); - err.span_suggestion_verbose( - found_span, - "change the closure to take multiple arguments instead of a single tuple", - format!("|{sugg}|"), - Applicability::MachineApplicable, - ); - } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] - && fields.len() == found_args.len() - && is_closure - { - let sugg = format!( - "|({}){}|", - found_args - .iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!( - ": ({})", - fields - .iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ") - ) - } else { - String::new() - }, - ); - err.span_suggestion_verbose( - found_span, - "change the closure to accept a tuple instead of individual arguments", - sugg, - Applicability::MachineApplicable, - ); - } - } - - err - } - - fn type_implements_fn_trait( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: ty::Binder<'tcx, Ty<'tcx>>, - polarity: ty::ImplPolarity, - ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { - self.commit_if_ok(|_| { - for trait_def_id in [ - self.tcx.lang_items().fn_trait(), - self.tcx.lang_items().fn_mut_trait(), - self.tcx.lang_items().fn_once_trait(), - ] { - let Some(trait_def_id) = trait_def_id else { continue }; - // Make a fresh inference variable so we can determine what the substitutions - // of the trait are. - let var = self.next_ty_var(TypeVariableOrigin { - span: DUMMY_SP, - kind: TypeVariableOriginKind::MiscVariable, - }); - // FIXME(effects) - let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); - let obligation = Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - ty.rebind(ty::TraitPredicate { trait_ref, polarity }), - ); - let ocx = ObligationCtxt::new(self); - ocx.register_obligation(obligation); - if ocx.select_all_or_error().is_empty() { - return Ok(( - self.tcx - .fn_trait_kind_from_def_id(trait_def_id) - .expect("expected to map DefId to ClosureKind"), - ty.rebind(self.resolve_vars_if_possible(var)), - )); - } - } - - Err(()) - }) - } -} - -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { - fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed { - #[derive(Debug)] - struct ErrorDescriptor<'tcx> { - predicate: ty::Predicate<'tcx>, - index: Option, // None if this is an old error - } - - let mut error_map: FxIndexMap<_, Vec<_>> = self - .reported_trait_errors - .borrow() - .iter() - .map(|(&span, predicates)| { - ( - span, - predicates - .iter() - .map(|&predicate| ErrorDescriptor { predicate, index: None }) - .collect(), - ) - }) - .collect(); - - for (index, error) in errors.iter().enumerate() { - // We want to ignore desugarings here: spans are equivalent even - // if one is the result of a desugaring and the other is not. - let mut span = error.obligation.cause.span; - let expn_data = span.ctxt().outer_expn_data(); - if let ExpnKind::Desugaring(_) = expn_data.kind { - span = expn_data.call_site; - } - - error_map.entry(span).or_default().push(ErrorDescriptor { - predicate: error.obligation.predicate, - index: Some(index), - }); - - self.reported_trait_errors - .borrow_mut() - .entry(span) - .or_default() - .push(error.obligation.predicate); - } - - // We do this in 2 passes because we want to display errors in order, though - // maybe it *is* better to sort errors by span or something. - let mut is_suppressed = vec![false; errors.len()]; - for (_, error_set) in error_map.iter() { - // We want to suppress "duplicate" errors with the same span. - for error in error_set { - if let Some(index) = error.index { - // Suppress errors that are either: - // 1) strictly implied by another error. - // 2) implied by an error with a smaller index. - for error2 in error_set { - if error2.index.is_some_and(|index2| is_suppressed[index2]) { - // Avoid errors being suppressed by already-suppressed - // errors, to prevent all errors from being suppressed - // at once. - continue; - } - - if self.error_implies(error2.predicate, error.predicate) - && !(error2.index >= error.index - && self.error_implies(error.predicate, error2.predicate)) - { - info!("skipping {:?} (implied by {:?})", error, error2); - is_suppressed[index] = true; - break; - } - } - } - } - } - - for from_expansion in [false, true] { - for (error, suppressed) in iter::zip(errors, &is_suppressed) { - if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { - self.report_fulfillment_error(error); - } - } - } - - self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors") - } - - /// Reports that an overflow has occurred and halts compilation. We - /// halt compilation unconditionally because it is important that - /// overflows never be masked -- they basically represent computations - /// whose result could not be truly determined and thus we can't say - /// if the program type checks or not -- and they are unusual - /// occurrences in any case. - fn report_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - mutate: impl FnOnce(&mut Diagnostic), - ) -> ! - where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, - { - let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); - mutate(&mut err); - err.emit(); - - self.tcx.sess.abort_if_errors(); - bug!(); - } - - fn build_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> - where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, - { - let predicate = self.resolve_vars_if_possible(predicate.clone()); - let mut pred_str = predicate.to_string(); - - if pred_str.len() > 50 { - // We don't need to save the type to a file, we will be talking about this type already - // in a separate note when we explain the obligation, so it will be available that way. - pred_str = predicate - .print(FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(6), - )) - .unwrap() - .into_buffer(); - } - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0275, - "overflow evaluating the requirement `{}`", - pred_str, - ); - - if suggest_increasing_limit { - self.suggest_new_overflow_limit(&mut err); - } - - err - } - - /// Reports that an overflow has occurred and halts compilation. We - /// halt compilation unconditionally because it is important that - /// overflows never be masked -- they basically represent computations - /// whose result could not be truly determined and thus we can't say - /// if the program type checks or not -- and they are unusual - /// occurrences in any case. - fn report_overflow_obligation( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: ToPredicate<'tcx> + Clone, - { - let predicate = obligation.predicate.clone().to_predicate(self.tcx); - let predicate = self.resolve_vars_if_possible(predicate); - self.report_overflow_error( - &predicate, - obligation.cause.span, - suggest_increasing_limit, - |err| { - self.note_obligation_cause_code( - obligation.cause.body_id, - err, - predicate, - obligation.param_env, - obligation.cause.code(), - &mut vec![], - &mut Default::default(), - ); - }, - ); - } - - fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) { - let suggested_limit = match self.tcx.recursion_limit() { - Limit(0) => Limit(2), - limit => limit * 2, - }; - err.help(format!( - "consider increasing the recursion limit by adding a \ - `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", - suggested_limit, - self.tcx.crate_name(LOCAL_CRATE), - )); - } - - /// Reports that a cycle was detected which led to overflow and halts - /// compilation. This is equivalent to `report_overflow_obligation` except - /// that we can give a more helpful error message (and, in particular, - /// we do not suggest increasing the overflow limit, which is not - /// going to help). - fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { - let cycle = self.resolve_vars_if_possible(cycle.to_owned()); - assert!(!cycle.is_empty()); - - debug!(?cycle, "report_overflow_error_cycle"); - - // The 'deepest' obligation is most likely to have a useful - // cause 'backtrace' - self.report_overflow_obligation( - cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), - false, - ); - } - - fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed { - let obligation = self.resolve_vars_if_possible(obligation); - let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true); - self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); - err.emit() - } - - fn report_selection_error( - &self, - mut obligation: PredicateObligation<'tcx>, - root_obligation: &PredicateObligation<'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( - tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"), - ); - - let mut err = match *error { - SelectionError::Unimplemented => { - // If this obligation was generated as a result of well-formedness checking, see if we - // can get a better error message by performing HIR-based well-formedness checking. - if let ObligationCauseCode::WellFormed(Some(wf_loc)) = - root_obligation.cause.code().peel_derives() - && !obligation.predicate.has_non_region_infer() - { - if let Some(cause) = self - .tcx - .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc)) - { - obligation.cause = cause.clone(); - span = obligation.cause.span; - } - } - - if let ObligationCauseCode::CompareImplItemObligation { - impl_item_def_id, - trait_item_def_id, - kind: _, - } = *obligation.cause.code() - { - self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}`", obligation.predicate), - ) - .emit(); - return; - } - - // Report a const-param specific error - if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() - { - self.report_const_param_not_wf(ty, &obligation).emit(); - return; - } - - let bound_predicate = obligation.predicate.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { - let trait_predicate = bound_predicate.rebind(trait_predicate); - let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - - // FIXME(effects) - let predicate_is_const = false; - - if self.tcx.sess.has_errors().is_some() - && trait_predicate.references_error() - { - return; - } - let trait_ref = trait_predicate.to_poly_trait_ref(); - - let (post_message, pre_message, type_def) = self - .get_parent_trait_ref(obligation.cause.code()) - .map(|(t, s)| { - ( - format!(" in `{t}`"), - format!("within `{t}`, "), - s.map(|s| (format!("within this `{t}`"), s)), - ) - }) - .unwrap_or_default(); - - let OnUnimplementedNote { - message, - label, - note, - parent_label, - append_const_msg, - } = self.on_unimplemented_note(trait_ref, &obligation); - let have_alt_message = message.is_some() || label.is_some(); - let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); - let is_unsize = - Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); - let (message, note, append_const_msg) = if is_try_conversion { - ( - Some(format!( - "`?` couldn't convert the error to `{}`", - trait_ref.skip_binder().self_ty(), - )), - Some( - "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" - .to_owned(), - ), - Some(AppendConstMessage::Default), - ) - } else { - (message, note, append_const_msg) - }; - - let err_msg = self.get_standard_error_message( - &trait_predicate, - message, - predicate_is_const, - append_const_msg, - post_message, - ); - - let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id()) - == self.tcx.lang_items().transmute_trait() - { - // Recompute the safe transmute reason and use that for the error reporting - match self.get_safe_transmute_error_and_reason( - obligation.clone(), - trait_ref, - span, - ) { - GetSafeTransmuteErrorAndReason::Silent => return, - GetSafeTransmuteErrorAndReason::Error { - err_msg, - safe_transmute_explanation, - } => (err_msg, Some(safe_transmute_explanation)), - } - } else { - (err_msg, None) - }; - - let mut err = struct_span_err!(self.tcx.sess, span, E0277, "{}", err_msg); - - if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { - err.span_label( - ret_span, - format!( - "expected `{}` because of this", - trait_ref.skip_binder().self_ty() - ), - ); - } - - if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { - self.add_tuple_trait_message( - &obligation.cause.code().peel_derives(), - &mut err, - ); - } - - if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() - && predicate_is_const - { - err.note("`~const Drop` was renamed to `~const Destruct`"); - err.note("See for more details"); - } - - let explanation = get_explanation_based_on_obligation( - &obligation, - trait_ref, - &trait_predicate, - pre_message, - ); - - self.check_for_binding_assigned_block_without_tail_expression( - &obligation, - &mut err, - trait_predicate, - ); - if self.suggest_add_reference_to_arg( - &obligation, - &mut err, - trait_predicate, - have_alt_message, - ) { - self.note_obligation_cause(&mut err, &obligation); - err.emit(); - return; - } - if let Some(s) = label { - // If it has a custom `#[rustc_on_unimplemented]` - // error message, let's display it as the label! - err.span_label(span, s); - if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { - // When the self type is a type param We don't need to "the trait - // `std::marker::Sized` is not implemented for `T`" as we will point - // at the type param with a label to suggest constraining it. - err.help(explanation); - } - } else if let Some(custom_explanation) = safe_transmute_explanation { - err.span_label(span, custom_explanation); - } else { - err.span_label(span, explanation); - } - - if let ObligationCauseCode::Coercion { source, target } = - *obligation.cause.code().peel_derives() - { - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { - self.suggest_borrowing_for_object_cast( - &mut err, - &root_obligation, - source, - target, - ); - } - } - - let UnsatisfiedConst(unsatisfied_const) = self - .maybe_add_note_for_unsatisfied_const( - &obligation, - trait_ref, - &trait_predicate, - &mut err, - span, - ); - - if let Some((msg, span)) = type_def { - err.span_label(span, msg); - } - if let Some(s) = note { - // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(s); - } - if let Some(s) = parent_label { - let body = obligation.cause.body_id; - err.span_label(tcx.def_span(body), s); - } - - self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); - self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); - let mut suggested = - self.suggest_dereferences(&obligation, &mut err, trait_predicate); - suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); - let impl_candidates = self.find_similar_impl_candidates(trait_predicate); - suggested = if let &[cand] = &impl_candidates[..] { - let cand = cand.trait_ref; - if let (ty::FnPtr(_), ty::FnDef(..)) = - (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) - { - err.span_suggestion( - span.shrink_to_hi(), - format!( - "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`", - cand.print_only_trait_path(), - cand.self_ty(), - ), - format!(" as {}", cand.self_ty()), - Applicability::MaybeIncorrect, - ); - true - } else { - false - } - } else { - false - } || suggested; - suggested |= - self.suggest_remove_reference(&obligation, &mut err, trait_predicate); - suggested |= self.suggest_semicolon_removal( - &obligation, - &mut err, - span, - trait_predicate, - ); - self.note_version_mismatch(&mut err, &trait_ref); - self.suggest_remove_await(&obligation, &mut err); - self.suggest_derive(&obligation, &mut err, trait_predicate); - - if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { - self.suggest_await_before_try( - &mut err, - &obligation, - trait_predicate, - span, - ); - } - - if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { - err.emit(); - return; - } - - if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { - err.emit(); - return; - } - - if is_unsize { - // If the obligation failed due to a missing implementation of the - // `Unsize` trait, give a pointer to why that might be the case - err.note( - "all implementations of `Unsize` are provided \ - automatically by the compiler, see \ - \ - for more information", - ); - } - - let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); - let is_target_feature_fn = if let ty::FnDef(def_id, _) = - *trait_ref.skip_binder().self_ty().kind() - { - !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() - } else { - false - }; - if is_fn_trait && is_target_feature_fn { - err.note( - "`#[target_feature]` functions do not implement the `Fn` traits", - ); - } - - self.try_to_add_help_message( - &obligation, - trait_ref, - &trait_predicate, - &mut err, - span, - is_fn_trait, - suggested, - unsatisfied_const, - ); - - // Changing mutability doesn't make a difference to whether we have - // an `Unsize` impl (Fixes ICE in #71036) - if !is_unsize { - self.suggest_change_mut(&obligation, &mut err, trait_predicate); - } - - // If this error is due to `!: Trait` not implemented but `(): Trait` is - // implemented, and fallback has occurred, then it could be due to a - // variable that used to fallback to `()` now falling back to `!`. Issue a - // note informing about the change in behaviour. - if trait_predicate.skip_binder().self_ty().is_never() - && self.fallback_has_occurred - { - let predicate = trait_predicate.map_bound(|trait_pred| { - 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) { - err.note( - "this error might have been caused by changes to \ - Rust's type-inference algorithm (see issue #48950 \ - \ - for more information)", - ); - err.help("did you intend to use the type `()` here instead?"); - } - } - - self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause); - - // Return early if the trait is Debug or Display and the invocation - // originates within a standard library macro, because the output - // is otherwise overwhelming and unhelpful (see #85844 for an - // example). - - let in_std_macro = - match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { - Some(macro_def_id) => { - let crate_name = tcx.crate_name(macro_def_id.krate); - crate_name == sym::std || crate_name == sym::core - } - None => false, - }; - - if in_std_macro - && matches!( - self.tcx.get_diagnostic_name(trait_ref.def_id()), - Some(sym::Debug | sym::Display) - ) - { - err.emit(); - return; - } - - err - } - - ty::PredicateKind::Subtype(predicate) => { - // Errors for Subtype predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, - // not selection error. - span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) - } - - ty::PredicateKind::Coerce(predicate) => { - // Errors for Coerce predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, - // not selection error. - span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate) - } - - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => { - span_bug!( - span, - "outlives clauses should not error outside borrowck. obligation: `{:?}`", - obligation - ) - } - - ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { - span_bug!( - span, - "projection clauses should be implied from elsewhere. obligation: `{:?}`", - obligation - ) - } - - ty::PredicateKind::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); - report_object_safety_error(self.tcx, span, trait_def_id, violations) - } - - ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { - let found_kind = self.closure_kind(closure_args).unwrap(); - self.report_closure_error(&obligation, closure_def_id, found_kind, kind) - } - - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { - let ty = self.resolve_vars_if_possible(ty); - match self.tcx.sess.opts.unstable_opts.trait_solver { - TraitSolver::Classic => { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } - TraitSolver::Next | TraitSolver::NextCoherence => { - // FIXME: we'll need a better message which takes into account - // which bounds actually failed to hold. - self.tcx.sess.struct_span_err( - span, - format!("the type `{ty}` is not well-formed"), - ) - } - } - } - - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { - // Errors for `ConstEvaluatable` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. - span_bug!( - span, - "const-evaluatable requirement gave wrong error: `{:?}`", - obligation - ) - } - - ty::PredicateKind::ConstEquate(..) => { - // Errors for `ConstEquate` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. - span_bug!( - span, - "const-equate requirement gave wrong error: `{:?}`", - obligation - ) - } - - ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), - - ty::PredicateKind::AliasRelate(..) => span_bug!( - span, - "AliasRelate predicate should never be the predicate cause of a SelectionError" - ), - - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - let mut diag = self.tcx.sess.struct_span_err( - span, - format!("the constant `{ct}` is not of type `{ty}`"), - ); - self.note_type_err( - &mut diag, - &obligation.cause, - None, - None, - TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())), - false, - false, - ); - diag - } - } - } - - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { - found_trait_ref, - expected_trait_ref, - terr: terr @ TypeError::CyclicTy(_), - }) => self.report_type_parameter_mismatch_cyclic_type_error( - &obligation, - found_trait_ref, - expected_trait_ref, - terr, - ), - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { - found_trait_ref, - expected_trait_ref, - terr: _, - }) => { - match self.report_type_parameter_mismatch_error( - &obligation, - span, - found_trait_ref, - expected_trait_ref, - ) { - Some(err) => err, - None => return, - } - } - - 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) - } - - SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { - bug!( - "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" - ) - } - SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { - match self.report_not_const_evaluatable_error(&obligation, span) { - Some(err) => err, - None => return, - } - } - - // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | - // Already reported. - Overflow(OverflowError::Error(_)) => return, - - Overflow(_) => { - bug!("overflow should be handled before the `report_selection_error` path"); - } - SelectionError::ErrorReporting => { - bug!("ErrorReporting Overflow should not reach `report_selection_err` call") - } - }; - - self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); - err.emit(); - } - - fn report_const_param_not_wf( - &self, - ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let span = obligation.cause.span; - - let mut diag = match ty.kind() { - _ if ty.has_param() => { - span_bug!(span, "const param tys cannot mention other generic parameters"); - } - ty::Float(_) => { - struct_span_err!( - self.tcx.sess, - span, - E0741, - "`{ty}` is forbidden as the type of a const generic parameter", - ) - } - ty::FnPtr(_) => { - struct_span_err!( - self.tcx.sess, - span, - E0741, - "using function pointers as const generic parameters is forbidden", - ) - } - ty::RawPtr(_) => { - struct_span_err!( - self.tcx.sess, - span, - E0741, - "using raw pointers as const generic parameters is forbidden", - ) - } - ty::Adt(def, _) => { - // We should probably see if we're *allowed* to derive `ConstParamTy` on the type... - let mut diag = struct_span_err!( - self.tcx.sess, - span, - E0741, - "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter", - ); - // Only suggest derive if this isn't a derived obligation, - // and the struct is local. - if let Some(span) = self.tcx.hir().span_if_local(def.did()) - && obligation.cause.code().parent().is_none() - { - if ty.is_structural_eq_shallow(self.tcx) { - diag.span_suggestion( - span, - "add `#[derive(ConstParamTy)]` to the struct", - "#[derive(ConstParamTy)]\n", - Applicability::MachineApplicable, - ); - } else { - // FIXME(adt_const_params): We should check there's not already an - // overlapping `Eq`/`PartialEq` impl. - diag.span_suggestion( - span, - "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct", - "#[derive(ConstParamTy, PartialEq, Eq)]\n", - Applicability::MachineApplicable, - ); - } - } - diag - } - _ => { - struct_span_err!( - self.tcx.sess, - span, - E0741, - "`{ty}` can't be used as a const parameter type", - ) - } - }; - - let mut code = obligation.cause.code(); - let mut pred = obligation.predicate.to_opt_poly_trait_pred(); - while let Some((next_code, next_pred)) = code.parent() { - if let Some(pred) = pred { - let pred = self.instantiate_binder_with_placeholders(pred); - diag.note(format!( - "`{}` must implement `{}`, but it does not", - pred.self_ty(), - pred.print_modifiers_and_trait_path() - )); - } - code = next_code; - pred = next_pred; - } - - diag - } -} - -trait InferCtxtPrivExt<'tcx> { - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; - - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>); - - fn report_projection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, - ); - - fn maybe_detailed_projection_msg( - &self, - pred: ty::ProjectionPredicate<'tcx>, - normalized_ty: ty::Term<'tcx>, - expected_ty: ty::Term<'tcx>, - ) -> Option; - - fn fuzzy_match_tys( - &self, - a: Ty<'tcx>, - b: Ty<'tcx>, - ignoring_lifetimes: bool, - ) -> Option; - - fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>; - - fn find_similar_impl_candidates( - &self, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> Vec>; - - fn report_similar_impl_candidates( - &self, - impl_candidates: &[ImplCandidate<'tcx>], - trait_ref: ty::PolyTraitRef<'tcx>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - other: bool, - ) -> bool; - - fn report_similar_impl_candidates_for_root_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - ); - - /// Gets the parent trait chain start - fn get_parent_trait_ref( - &self, - code: &ObligationCauseCode<'tcx>, - ) -> Option<(String, Option)>; - - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> bool; - - /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the - /// `trait_ref`. - /// - /// For this to work, `new_self_ty` must have no escaping bound variables. - fn mk_trait_obligation_with_new_self_ty( - &self, - param_env: ty::ParamEnv<'tcx>, - trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, - ) -> PredicateObligation<'tcx>; - - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>); - - fn predicate_can_apply( - &self, - param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); - - fn suggest_unsized_bound_if_applicable( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ); - - fn annotate_source_of_ambiguity( - &self, - err: &mut Diagnostic, - impls: &[ambiguity::Ambiguity], - predicate: ty::Predicate<'tcx>, - ); - - fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>); - - fn maybe_indirection_for_unsized( - &self, - err: &mut Diagnostic, - item: &'tcx Item<'tcx>, - param: &'tcx GenericParam<'tcx>, - ) -> bool; - - fn is_recursive_obligation( - &self, - obligated_types: &mut Vec>, - cause_code: &ObligationCauseCode<'tcx>, - ) -> bool; - - fn get_standard_error_message( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - message: Option, - predicate_is_const: bool, - append_const_msg: Option, - post_message: String, - ) -> String; - - fn get_safe_transmute_error_and_reason( - &self, - obligation: PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - ) -> GetSafeTransmuteErrorAndReason; - - fn add_tuple_trait_message( - &self, - obligation_cause_code: &ObligationCauseCode<'tcx>, - err: &mut Diagnostic, - ); - - fn try_to_add_help_message( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - is_fn_trait: bool, - suggested: bool, - unsatisfied_const: bool, - ); - - fn add_help_message_for_fn_trait( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - err: &mut Diagnostic, - implemented_kind: ty::ClosureKind, - params: ty::Binder<'tcx, Ty<'tcx>>, - ); - - fn maybe_add_note_for_unsatisfied_const( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - ) -> UnsatisfiedConst; - - fn report_closure_error( - &self, - obligation: &PredicateObligation<'tcx>, - closure_def_id: DefId, - found_kind: ty::ClosureKind, - kind: ty::ClosureKind, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; - - fn report_type_parameter_mismatch_cyclic_type_error( - &self, - obligation: &PredicateObligation<'tcx>, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'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>, - span: Span, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option>; - - fn report_not_const_evaluatable_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - ) -> Option>; -} - -impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { - if cond == error { - return true; - } - - // FIXME: It should be possible to deal with `ForAll` in a cleaner way. - let bound_error = error.kind(); - let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), - ) => (cond, bound_error.rebind(error)), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for pred in super::elaborate(self.tcx, std::iter::once(cond)) { - let bound_predicate = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = - bound_predicate.skip_binder() - { - let error = error.to_poly_trait_ref(); - let implication = bound_predicate.rebind(implication.trait_ref); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication) { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } - } - - false - } - - #[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( - error.obligation.clone(), - &error.root_obligation, - selection_error, - ); - } - FulfillmentErrorCode::CodeProjectionError(ref e) => { - self.report_projection_error(&error.obligation, e); - } - FulfillmentErrorCode::CodeAmbiguity { overflow: false } => { - self.maybe_report_ambiguity(&error.obligation); - } - FulfillmentErrorCode::CodeAmbiguity { overflow: true } => { - self.report_overflow_no_abort(error.obligation.clone()); - } - FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types( - &error.obligation.cause, - expected_found.expected, - expected_found.found, - *err, - ) - .emit(); - } - FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { - let mut diag = self.report_mismatched_consts( - &error.obligation.cause, - expected_found.expected, - expected_found.found, - *err, - ); - let code = error.obligation.cause.code().peel_derives().peel_match_impls(); - if let ObligationCauseCode::BindingObligation(..) - | ObligationCauseCode::ItemObligation(..) - | ObligationCauseCode::ExprBindingObligation(..) - | ObligationCauseCode::ExprItemObligation(..) = code - { - self.note_obligation_cause_code( - error.obligation.cause.body_id, - &mut diag, - error.obligation.predicate, - error.obligation.param_env, - code, - &mut vec![], - &mut Default::default(), - ); - } - diag.emit(); - } - FulfillmentErrorCode::CodeCycle(ref cycle) => { - self.report_overflow_obligation_cycle(cycle); - } - } - } - - #[instrument(level = "debug", skip_all)] - fn report_projection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, - ) { - let predicate = self.resolve_vars_if_possible(obligation.predicate); - - if predicate.references_error() { - return; - } - - self.probe(|_| { - let ocx = ObligationCtxt::new(self); - - // try to find the mismatched types to report the error with. - // - // this can fail if the problem was higher-ranked, in which - // cause I have no idea for a good error message. - let bound_predicate = predicate.kind(); - let (values, err) = if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) = - bound_predicate.skip_binder() - { - let data = self.instantiate_binder_with_fresh_vars( - obligation.cause.span, - infer::LateBoundRegionConversionTime::HigherRankedType, - bound_predicate.rebind(data), - ); - let unnormalized_term = match data.term.unpack() { - ty::TermKind::Ty(_) => Ty::new_projection( - self.tcx, - data.projection_ty.def_id, - data.projection_ty.args, - ) - .into(), - ty::TermKind::Const(ct) => ty::Const::new_unevaluated( - self.tcx, - ty::UnevaluatedConst { - def: data.projection_ty.def_id, - args: data.projection_ty.args, - }, - ct.ty(), - ) - .into(), - }; - // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice - // to deeply normalize this type. - let normalized_term = - ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term); - - debug!(?obligation.cause, ?obligation.param_env); - - debug!(?normalized_term, data.ty = ?data.term); - - let is_normalized_term_expected = !matches!( - obligation.cause.code().peel_derives(), - ObligationCauseCode::ItemObligation(_) - | ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ExprItemObligation(..) - | ObligationCauseCode::ExprBindingObligation(..) - | ObligationCauseCode::Coercion { .. } - | ObligationCauseCode::OpaqueType - ); - - // constrain inference variables a bit more to nested obligations from normalize so - // we can have more helpful errors. - // - // we intentionally drop errors from normalization here, - // since the normalization is just done to improve the error message. - let _ = ocx.select_where_possible(); - - if let Err(new_err) = ocx.eq_exp( - &obligation.cause, - obligation.param_env, - is_normalized_term_expected, - normalized_term, - data.term, - ) { - (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err) - } else { - (None, error.err) - } - } else { - (None, error.err) - }; - - let msg = values - .and_then(|(predicate, _, normalized_term, expected_term)| { - self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term) - }) - .unwrap_or_else(|| { - with_forced_trimmed_paths!(format!( - "type mismatch resolving `{}`", - self.resolve_vars_if_possible(predicate) - .print(FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(10), - )) - .unwrap() - .into_buffer() - )) - }); - let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); - - let secondary_span = (|| { - let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = - predicate.kind().skip_binder() - else { - return None; - }; - - let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?; - let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - - let mut associated_items = vec![]; - self.tcx.for_each_relevant_impl( - self.tcx.trait_of_item(proj.projection_ty.def_id)?, - proj.projection_ty.self_ty(), - |impl_def_id| { - associated_items.extend( - self.tcx - .associated_items(impl_def_id) - .in_definition_order() - .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident), - ); - }, - ); - - let [associated_item]: &[ty::AssocItem] = &associated_items[..] else { - return None; - }; - match self.tcx.hir().get_if_local(associated_item.def_id) { - Some( - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Type(_, Some(ty)), - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(ty), - .. - }), - ) => Some(( - ty.span, - with_forced_trimmed_paths!(Cow::from(format!( - "type mismatch resolving `{}`", - self.resolve_vars_if_possible(predicate) - .print(FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(5), - )) - .unwrap() - .into_buffer() - ))), - )), - _ => None, - } - })(); - - self.note_type_err( - &mut diag, - &obligation.cause, - secondary_span, - values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| { - infer::ValuePairs::Terms(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - expected_ty, - )) - }), - err, - true, - false, - ); - self.note_obligation_cause(&mut diag, obligation); - diag.emit(); - }); - } - - fn maybe_detailed_projection_msg( - &self, - pred: ty::ProjectionPredicate<'tcx>, - normalized_ty: ty::Term<'tcx>, - expected_ty: ty::Term<'tcx>, - ) -> Option { - let trait_def_id = pred.projection_ty.trait_def_id(self.tcx); - let self_ty = pred.projection_ty.self_ty(); - - with_forced_trimmed_paths! { - if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() { - let fn_kind = self_ty.prefix_string(self.tcx); - let item = match self_ty.kind() { - ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(), - _ => self_ty.to_string(), - }; - Some(format!( - "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \ - returns `{normalized_ty}`", - )) - } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() { - Some(format!( - "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \ - resolves to `{normalized_ty}`" - )) - } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) { - Some(format!( - "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \ - yields `{normalized_ty}`" - )) - } else { - None - } - } - } - - fn fuzzy_match_tys( - &self, - mut a: Ty<'tcx>, - mut b: Ty<'tcx>, - ignoring_lifetimes: bool, - ) -> Option { - /// returns the fuzzy category of a given type, or None - /// if the type can be equated to any type. - fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option { - match t.kind() { - ty::Bool => Some(0), - ty::Char => Some(1), - ty::Str => Some(2), - ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2), - ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4), - ty::Ref(..) | ty::RawPtr(..) => Some(5), - ty::Array(..) | ty::Slice(..) => Some(6), - ty::FnDef(..) | ty::FnPtr(..) => Some(7), - ty::Dynamic(..) => Some(8), - ty::Closure(..) => Some(9), - ty::Tuple(..) => Some(10), - ty::Param(..) => Some(11), - ty::Alias(ty::Projection, ..) => Some(12), - ty::Alias(ty::Inherent, ..) => Some(13), - ty::Alias(ty::Opaque, ..) => Some(14), - ty::Alias(ty::Weak, ..) => Some(15), - ty::Never => Some(16), - ty::Adt(..) => Some(17), - ty::Generator(..) => Some(18), - ty::Foreign(..) => Some(19), - ty::GeneratorWitness(..) => Some(20), - ty::GeneratorWitnessMIR(..) => Some(21), - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, - } - } - - let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> { - loop { - match t.kind() { - ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => { - t = *inner - } - _ => break t, - } - } - }; - - if !ignoring_lifetimes { - a = strip_references(a); - b = strip_references(b); - } - - let cat_a = type_category(self.tcx, a)?; - let cat_b = type_category(self.tcx, b)?; - if a == b { - Some(CandidateSimilarity::Exact { ignoring_lifetimes }) - } else if cat_a == cat_b { - match (a.kind(), b.kind()) { - (ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b, - (ty::Foreign(def_a), ty::Foreign(def_b)) => def_a == def_b, - // Matching on references results in a lot of unhelpful - // suggestions, so let's just not do that for now. - // - // We still upgrade successful matches to `ignoring_lifetimes: true` - // to prioritize that impl. - (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => { - self.fuzzy_match_tys(a, b, true).is_some() - } - _ => true, - } - .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes }) - } else if ignoring_lifetimes { - None - } else { - self.fuzzy_match_tys(a, b, true) - } - } - - fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { - self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { - hir::GeneratorKind::Gen => "a generator", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", - }) - } - - fn find_similar_impl_candidates( - &self, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> Vec> { - let mut candidates: Vec<_> = self - .tcx - .all_impls(trait_pred.def_id()) - .filter_map(|def_id| { - if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative - || !self.tcx.is_user_visible_dep(def_id.krate) - { - return None; - } - - let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder(); - - self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false) - .map(|similarity| ImplCandidate { trait_ref: imp, similarity }) - }) - .collect(); - if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) { - // If any of the candidates is a perfect match, we don't want to show all of them. - // This is particularly relevant for the case of numeric types (as they all have the - // same category). - candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })); - } - candidates - } - - fn report_similar_impl_candidates( - &self, - impl_candidates: &[ImplCandidate<'tcx>], - trait_ref: ty::PolyTraitRef<'tcx>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - other: bool, - ) -> bool { - let other = if other { "other " } else { "" }; - let report = |candidates: Vec>, err: &mut Diagnostic| { - if candidates.is_empty() { - return false; - } - if let &[cand] = &candidates[..] { - let (desc, mention_castable) = - match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { - (ty::FnPtr(_), ty::FnDef(..)) => { - (" implemented for fn pointer `", ", cast using `as`") - } - (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""), - _ => (" implemented for `", ""), - }; - err.highlighted_help(vec![ - (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle), - ("is".to_string(), Style::Highlight), - (desc.to_string(), Style::NoStyle), - (cand.self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - (mention_castable.to_string(), Style::NoStyle), - ]); - return true; - } - let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id); - // Check if the trait is the same in all cases. If so, we'll only show the type. - let mut traits: Vec<_> = - 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 args[1..] is the same. - let all_traits_equal = traits.len() == 1; - - let candidates: Vec = candidates - .into_iter() - .map(|c| { - if all_traits_equal { - format!("\n {}", c.self_ty()) - } else { - format!("\n {c}") - } - }) - .collect(); - - 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 candidates.len() > 9 { - format!("\nand {} others", candidates.len() - 8) - } else { - String::new() - } - )); - true - }; - - let def_id = trait_ref.def_id(); - if impl_candidates.is_empty() { - if self.tcx.trait_is_auto(def_id) - || self.tcx.lang_items().iter().any(|(_, id)| id == def_id) - || self.tcx.get_diagnostic_name(def_id).is_some() - { - // Mentioning implementers of `Copy`, `Debug` and friends is not useful. - return false; - } - let mut impl_candidates: Vec<_> = self - .tcx - .all_impls(def_id) - // Ignore automatically derived impls and `!Trait` impls. - .filter(|&def_id| { - self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative - || self.tcx.is_automatically_derived(def_id) - }) - .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) - .map(ty::EarlyBinder::instantiate_identity) - .filter(|trait_ref| { - let self_ty = trait_ref.self_ty(); - // Avoid mentioning type parameters. - if let ty::Param(_) = self_ty.kind() { - false - } - // Avoid mentioning types that are private to another crate - else if let ty::Adt(def, _) = self_ty.peel_refs().kind() { - // FIXME(compiler-errors): This could be generalized, both to - // be more granular, and probably look past other `#[fundamental]` - // types, too. - self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx) - } else { - true - } - }) - .collect(); - - impl_candidates.sort(); - impl_candidates.dedup(); - return report(impl_candidates, err); - } - - // Sort impl candidates so that ordering is consistent for UI tests. - // because the ordering of `impl_candidates` may not be deterministic: - // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 - // - // Prefer more similar candidates first, then sort lexicographically - // by their normalized string representation. - let mut impl_candidates: Vec<_> = impl_candidates - .iter() - .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.normalize(self.tcx, ty::ParamEnv::empty()), - }); - cand - }) - .collect(); - impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref)); - impl_candidates.dedup(); - - report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err) - } - - fn report_similar_impl_candidates_for_root_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - ) { - // This is *almost* equivalent to - // `obligation.cause.code().peel_derives()`, but it gives us the - // trait predicate for that corresponding root obligation. This - // lets us get a derived obligation from a type parameter, like - // when calling `string.strip_suffix(p)` where `p` is *not* an - // implementer of `Pattern<'_>`. - let mut code = obligation.cause.code(); - let mut trait_pred = trait_predicate; - let mut peeled = false; - while let Some((parent_code, parent_trait_pred)) = code.parent() { - code = parent_code; - if let Some(parent_trait_pred) = parent_trait_pred { - trait_pred = parent_trait_pred; - peeled = true; - } - } - let def_id = trait_pred.def_id(); - // Mention *all* the `impl`s for the *top most* obligation, the - // user might have meant to use one of them, if any found. We skip - // auto-traits or fundamental traits that might not be exactly what - // the user might expect to be presented with. Instead this is - // useful for less general traits. - if peeled - && !self.tcx.trait_is_auto(def_id) - && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id) - { - let trait_ref = trait_pred.to_poly_trait_ref(); - let impl_candidates = self.find_similar_impl_candidates(trait_pred); - self.report_similar_impl_candidates( - &impl_candidates, - trait_ref, - body_def_id, - err, - true, - ); - } - } - - /// Gets the parent trait chain start - fn get_parent_trait_ref( - &self, - code: &ObligationCauseCode<'tcx>, - ) -> Option<(String, Option)> { - match code { - ObligationCauseCode::BuiltinDerivedObligation(data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); - match self.get_parent_trait_ref(&data.parent_code) { - Some(t) => Some(t), - None => { - let ty = parent_trait_ref.skip_binder().self_ty(); - let span = TyCategory::from_ty(self.tcx, ty) - .map(|(_, def_id)| self.tcx.def_span(def_id)); - Some((ty.to_string(), span)) - } - } - } - ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { - self.get_parent_trait_ref(&parent_code) - } - _ => None, - } - } - - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> bool { - let get_trait_impls = |trait_def_id| { - let mut trait_impls = vec![]; - self.tcx.for_each_relevant_impl( - trait_def_id, - trait_ref.skip_binder().self_ty(), - |impl_def_id| { - trait_impls.push(impl_def_id); - }, - ); - trait_impls - }; - - let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); - let traits_with_same_path: std::collections::BTreeSet<_> = self - .tcx - .all_traits() - .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) - .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) - .collect(); - let mut suggested = false; - for trait_with_same_path in traits_with_same_path { - let trait_impls = get_trait_impls(trait_with_same_path); - if trait_impls.is_empty() { - continue; - } - let impl_spans: Vec<_> = - trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect(); - err.span_help( - impl_spans, - format!("trait impl{} with same name found", pluralize!(trait_impls.len())), - ); - let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); - let crate_msg = - format!("perhaps two different versions of crate `{trait_crate}` are being used?"); - err.note(crate_msg); - suggested = true; - } - suggested - } - - fn mk_trait_obligation_with_new_self_ty( - &self, - param_env: ty::ParamEnv<'tcx>, - trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, - ) -> PredicateObligation<'tcx> { - let trait_pred = - trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty)); - - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred) - } - - #[instrument(skip(self), level = "debug")] - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { - // Unable to successfully determine, probably means - // insufficient type information, but could mean - // ambiguous impls. The latter *ought* to be a - // coherence violation, so we don't report it here. - - let predicate = self.resolve_vars_if_possible(obligation.predicate); - let span = obligation.cause.span; - - debug!(?predicate, obligation.cause.code = ?obligation.cause.code()); - - // Ambiguity errors are often caused as fallout from earlier errors. - // We ignore them if this `infcx` is tainted in some cases below. - - let bound_predicate = predicate.kind(); - let mut err = match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - let trait_ref = bound_predicate.rebind(data.trait_ref); - debug!(?trait_ref); - - if predicate.references_error() { - return; - } - - // This is kind of a hack: it frequently happens that some earlier - // error prevents types from being fully inferred, and then we get - // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we - // could just skip over all checks where the self-ty is an - // inference variable, but I was afraid that there might be an - // inference variable created, registered as an obligation, and - // then never forced by writeback, and hence by skipping here we'd - // be ignoring the fact that we don't KNOW the type works - // out. Though even that would probably be harmless, given that - // we're only talking about builtin traits, which are known to be - // inhabited. We used to check for `self.tcx.sess.has_errors()` to - // avoid inundating the user with unnecessary errors, but we now - // check upstream for type errors and don't add the obligations to - // begin with in those cases. - if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - if let None = self.tainted_by_errors() { - self.emit_inference_failure_err( - obligation.cause.body_id, - span, - trait_ref.self_ty().skip_binder().into(), - ErrorCode::E0282, - false, - ) - .emit(); - } - return; - } - - // Typically, this ambiguity should only happen if - // there are unresolved type inference variables - // (otherwise it would suggest a coherence - // failure). But given #21974 that is not necessarily - // the case -- we can have multiple where clauses that - // are only distinguished by a region, which results - // in an ambiguity even when all types are fully - // known, since we don't dispatch based on region - // relationships. - - // Pick the first substitution that still contains inference variables as the one - // we're going to emit an error for. If there are none (see above), fall back to - // a more general error. - let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer()); - - let mut err = if let Some(subst) = subst { - self.emit_inference_failure_err( - obligation.cause.body_id, - span, - subst, - ErrorCode::E0283, - true, - ) - } else { - struct_span_err!( - self.tcx.sess, - span, - E0283, - "type annotations needed: cannot satisfy `{}`", - predicate, - ) - }; - - let ambiguities = ambiguity::recompute_applicable_impls( - self.infcx, - &obligation.with(self.tcx, trait_ref), - ); - let has_non_region_infer = - trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer()); - // It doesn't make sense to talk about applicable impls if there are more - // than a handful of them. - if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { - if self.tainted_by_errors().is_some() && subst.is_none() { - // If `subst.is_none()`, then this is probably two param-env - // candidates or impl candidates that are equal modulo lifetimes. - // Therefore, if we've already emitted an error, just skip this - // one, since it's not particularly actionable. - err.cancel(); - return; - } - self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate); - } else { - if self.tainted_by_errors().is_some() { - err.cancel(); - return; - } - err.note(format!("cannot satisfy `{predicate}`")); - let impl_candidates = self - .find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap()); - if impl_candidates.len() < 10 { - self.report_similar_impl_candidates( - impl_candidates.as_slice(), - trait_ref, - obligation.cause.body_id, - &mut err, - false, - ); - } - } - - if let ObligationCauseCode::ItemObligation(def_id) - | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() - { - self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); - } - - if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack()) - && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) - { - let mut expr_finder = FindExprBySpan::new(span); - expr_finder.visit_expr(&self.tcx.hir().body(body_id).value); - - if let Some(hir::Expr { - kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. } - ) = expr_finder.result - && let [ - .., - trait_path_segment @ hir::PathSegment { - res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id), - .. - }, - hir::PathSegment { - ident: assoc_item_name, - res: rustc_hir::def::Res::Def(_, item_id), - .. - } - ] = path.segments - && data.trait_ref.def_id == *trait_id - && self.tcx.trait_of_item(*item_id) == Some(*trait_id) - && let None = self.tainted_by_errors() - { - let (verb, noun) = match self.tcx.associated_item(item_id).kind { - ty::AssocKind::Const => ("refer to the", "constant"), - ty::AssocKind::Fn => ("call", "function"), - ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here - }; - - // Replace the more general E0283 with a more specific error - err.cancel(); - err = self.tcx.sess.struct_span_err_with_code( - span, - format!( - "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type", - ), - rustc_errors::error_code!(E0790), - ); - - if let Some(local_def_id) = data.trait_ref.def_id.as_local() - && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id) - && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) { - err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here")); - } - - err.span_label(span, format!("cannot {verb} associated {noun} of trait")); - - let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id); - - if trait_impls.blanket_impls().is_empty() - && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() - { - let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count(); - // If there is only one implementation of the trait, suggest using it. - // Otherwise, use a placeholder comment for the implementation. - let (message, impl_suggestion) = if non_blanket_impl_count == 1 {( - "use the fully-qualified path to the only available implementation", - format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity()) - )} else { - ("use a fully-qualified path to a specific available implementation", - " - // must be '::' between them, otherwise the parser won't accept the code - suggestions.push((between_span, "".to_string(),)); - suggestions.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string())); - } else { - suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), ">".to_string())); - } - err.multipart_suggestion( - message, - suggestions, - Applicability::MaybeIncorrect - ); - } - } - }; - - err - } - - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - // Same hacky approach as above to avoid deluging user - // with error messages. - if arg.references_error() - || self.tcx.sess.has_errors().is_some() - || self.tainted_by_errors().is_some() - { - return; - } - - self.emit_inference_failure_err( - obligation.cause.body_id, - span, - arg, - ErrorCode::E0282, - false, - ) - } - - ty::PredicateKind::Subtype(data) => { - if data.references_error() - || self.tcx.sess.has_errors().is_some() - || self.tainted_by_errors().is_some() - { - // no need to overload user in such cases - return; - } - let SubtypePredicate { a_is_expected: _, a, b } = data; - // both must be type variables, or the other would've been instantiated - assert!(a.is_ty_var() && b.is_ty_var()); - self.emit_inference_failure_err( - obligation.cause.body_id, - span, - a.into(), - ErrorCode::E0282, - true, - ) - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; - } - let subst = data - .projection_ty - .args - .iter() - .chain(Some(data.term.into_arg())) - .find(|g| g.has_non_region_infer()); - if let Some(subst) = subst { - let mut err = self.emit_inference_failure_err( - obligation.cause.body_id, - span, - subst, - ErrorCode::E0284, - true, - ); - err.note(format!("cannot satisfy `{predicate}`")); - err - } else { - // If we can't find a substitution, just print a generic error - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err - } - } - - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; - } - let subst = data.walk().find(|g| g.is_non_region_infer()); - if let Some(subst) = subst { - let err = self.emit_inference_failure_err( - obligation.cause.body_id, - span, - subst, - ErrorCode::E0284, - true, - ); - err - } else { - // If we can't find a substitution, just print a generic error - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err - } - } - _ => { - if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() { - return; - } - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err - } - }; - self.note_obligation_cause(&mut err, obligation); - err.emit(); - } - - fn annotate_source_of_ambiguity( - &self, - err: &mut Diagnostic, - ambiguities: &[ambiguity::Ambiguity], - predicate: ty::Predicate<'tcx>, - ) { - let mut spans = vec![]; - let mut crates = vec![]; - let mut post = vec![]; - let mut has_param_env = false; - for ambiguity in ambiguities { - match ambiguity { - ambiguity::Ambiguity::DefId(impl_def_id) => { - match self.tcx.span_of_impl(*impl_def_id) { - Ok(span) => spans.push(span), - Err(name) => { - crates.push(name); - if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) { - post.push(header); - } - } - } - } - ambiguity::Ambiguity::ParamEnv(span) => { - has_param_env = true; - spans.push(*span); - } - } - } - let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect(); - crate_names.sort(); - crate_names.dedup(); - post.sort(); - post.dedup(); - - if self.tainted_by_errors().is_some() - && (crate_names.len() == 1 - && spans.len() == 0 - && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) - || predicate.visit_with(&mut HasNumericInferVisitor).is_break()) - { - // Avoid complaining about other inference issues for expressions like - // `42 >> 1`, where the types are still `{integer}`, but we want to - // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too? - // NOTE(eddyb) this was `.cancel()`, but `err` - // is borrowed, so we can't fully defuse it. - err.downgrade_to_delayed_bug(); - return; - } - - let msg = format!( - "multiple `impl`s{} satisfying `{}` found", - if has_param_env { " or `where` clauses" } else { "" }, - predicate - ); - let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { - format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::>().join("\n"),) - } else if post.len() == 1 { - format!(": `{}`", post[0]) - } else { - String::new() - }; - - match (spans.len(), crates.len(), crate_names.len()) { - (0, 0, 0) => { - err.note(format!("cannot satisfy `{predicate}`")); - } - (0, _, 1) => { - err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,)); - } - (0, _, _) => { - err.note(format!( - "{} in the following crates: {}{}", - msg, - crate_names.join(", "), - post, - )); - } - (_, 0, 0) => { - let span: MultiSpan = spans.into(); - err.span_note(span, msg); - } - (_, 1, 1) => { - let span: MultiSpan = spans.into(); - err.span_note(span, msg); - err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,)); - } - _ => { - let span: MultiSpan = spans.into(); - err.span_note(span, msg); - err.note(format!( - "and more `impl`s found in the following crates: {}{}", - crate_names.join(", "), - post, - )); - } - } - } - - /// Returns `true` if the trait predicate may apply for *some* assignment - /// to the type parameters. - fn predicate_can_apply( - &self, - param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool { - struct ParamToVarFolder<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, - var_map: FxHashMap, Ty<'tcx>>, - } - - impl<'a, 'tcx> TypeFolder> for ParamToVarFolder<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - 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::MiscVariable, - span: DUMMY_SP, - }) - }) - } else { - ty.super_fold_with(self) - } - } - } - - self.probe(|_| { - let cleaned_pred = - pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); - - let InferOk { value: cleaned_pred, .. } = - self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred); - - let obligation = - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred); - - self.predicate_may_hold(&obligation) - }) - } - - fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>) { - // First, attempt to add note to this error with an async-await-specific - // message, and fall back to regular note otherwise. - if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { - self.note_obligation_cause_code( - obligation.cause.body_id, - err, - obligation.predicate, - obligation.param_env, - obligation.cause.code(), - &mut vec![], - &mut Default::default(), - ); - self.suggest_unsized_bound_if_applicable(err, obligation); - } - } - - #[instrument(level = "debug", skip_all)] - fn suggest_unsized_bound_if_applicable( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ) { - let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = - obligation.predicate.kind().skip_binder() - else { - return; - }; - let (ObligationCauseCode::BindingObligation(item_def_id, span) - | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) = - *obligation.cause.code().peel_derives() - else { - return; - }; - debug!(?pred, ?item_def_id, ?span); - - let (Some(node), true) = ( - self.tcx.hir().get_if_local(item_def_id), - Some(pred.def_id()) == self.tcx.lang_items().sized_trait(), - ) else { - return; - }; - self.maybe_suggest_unsized_generics(err, span, node); - } - - #[instrument(level = "debug", skip_all)] - fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>) { - let Some(generics) = node.generics() else { - return; - }; - let sized_trait = self.tcx.lang_items().sized_trait(); - debug!(?generics.params); - debug!(?generics.predicates); - let Some(param) = generics.params.iter().find(|param| param.span == span) else { - return; - }; - // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit - // `Sized` bound is there intentionally and we don't need to suggest relaxing it. - let explicitly_sized = generics - .bounds_for_param(param.def_id) - .flat_map(|bp| bp.bounds) - .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait); - if explicitly_sized { - return; - } - debug!(?param); - match node { - hir::Node::Item( - item @ hir::Item { - // Only suggest indirection for uses of type parameters in ADTs. - kind: - hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..), - .. - }, - ) => { - if self.maybe_indirection_for_unsized(err, item, param) { - return; - } - } - _ => {} - }; - // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`. - let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param.def_id) - { - (s, " +") - } else { - (span.shrink_to_hi(), ":") - }; - err.span_suggestion_verbose( - span, - "consider relaxing the implicit `Sized` restriction", - format!("{separator} ?Sized"), - Applicability::MachineApplicable, - ); - } - - fn maybe_indirection_for_unsized( - &self, - err: &mut Diagnostic, - item: &Item<'tcx>, - param: &GenericParam<'tcx>, - ) -> bool { - // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a - // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S(T);` - // is not. Look for invalid "bare" parameter uses, and suggest using indirection. - let mut visitor = - FindTypeParam { param: param.name.ident().name, invalid_spans: vec![], nested: false }; - visitor.visit_item(item); - if visitor.invalid_spans.is_empty() { - return false; - } - let mut multispan: MultiSpan = param.span.into(); - multispan.push_span_label( - param.span, - format!("this could be changed to `{}: ?Sized`...", param.name.ident()), - ); - for sp in visitor.invalid_spans { - multispan.push_span_label( - sp, - format!("...if indirection were used here: `Box<{}>`", param.name.ident()), - ); - } - err.span_help( - multispan, - format!( - "you could relax the implicit `Sized` bound on `{T}` if it were \ - used through indirection like `&{T}` or `Box<{T}>`", - T = param.name.ident(), - ), - ); - true - } - - fn is_recursive_obligation( - &self, - obligated_types: &mut Vec>, - cause_code: &ObligationCauseCode<'tcx>, - ) -> bool { - if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); - let self_ty = parent_trait_ref.skip_binder().self_ty(); - if obligated_types.iter().any(|ot| ot == &self_ty) { - return true; - } - if let ty::Adt(def, args) = self_ty.kind() - && let [arg] = &args[..] - && let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Adt(inner_def, _) = ty.kind() - && inner_def == def - { - return true; - } - } - false - } - - fn get_standard_error_message( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - message: Option, - predicate_is_const: bool, - append_const_msg: Option, - post_message: String, - ) -> String { - message - .and_then(|cannot_do_this| { - match (predicate_is_const, append_const_msg) { - // do nothing if predicate is not const - (false, _) => Some(cannot_do_this), - // suggested using default post message - (true, Some(AppendConstMessage::Default)) => { - Some(format!("{cannot_do_this} in const contexts")) - } - // overridden post message - (true, Some(AppendConstMessage::Custom(custom_msg))) => { - Some(format!("{cannot_do_this}{custom_msg}")) - } - // fallback to generic message - (true, None) => None, - } - }) - .unwrap_or_else(|| { - format!("the trait bound `{trait_predicate}` is not satisfied{post_message}") - }) - } - - fn get_safe_transmute_error_and_reason( - &self, - obligation: PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - ) -> GetSafeTransmuteErrorAndReason { - use rustc_transmute::Answer; - - // Erase regions because layout code doesn't particularly care about regions. - let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref)); - - let src_and_dst = rustc_transmute::Types { - dst: trait_ref.args.type_at(0), - src: trait_ref.args.type_at(1), - }; - let scope = trait_ref.args.type_at(2); - let Some(assume) = rustc_transmute::Assume::from_const( - self.infcx.tcx, - obligation.param_env, - trait_ref.args.const_at(3), - ) else { - span_bug!( - span, - "Unable to construct rustc_transmute::Assume where it was previously possible" - ); - }; - - match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable( - obligation.cause, - src_and_dst, - scope, - assume, - ) { - Answer::No(reason) => { - let dst = trait_ref.args.type_at(0); - let src = trait_ref.args.type_at(1); - let err_msg = format!( - "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`" - ); - let safe_transmute_explanation = match reason { - rustc_transmute::Reason::SrcIsUnspecified => { - format!("`{src}` does not have a well-specified layout") - } - - rustc_transmute::Reason::DstIsUnspecified => { - format!("`{dst}` does not have a well-specified layout") - } - - rustc_transmute::Reason::DstIsBitIncompatible => { - format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`") - } - - rustc_transmute::Reason::DstIsPrivate => format!( - "`{dst}` is or contains a type or field that is not visible in that scope" - ), - rustc_transmute::Reason::DstIsTooBig => { - format!("The size of `{src}` is smaller than the size of `{dst}`") - } - rustc_transmute::Reason::SrcSizeOverflow => { - format!( - "values of the type `{src}` are too big for the current architecture" - ) - } - rustc_transmute::Reason::DstSizeOverflow => { - format!( - "values of the type `{dst}` are too big for the current architecture" - ) - } - rustc_transmute::Reason::DstHasStricterAlignment { - src_min_align, - dst_min_align, - } => { - format!( - "The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})" - ) - } - rustc_transmute::Reason::DstIsMoreUnique => { - format!("`{src}` is a shared reference, but `{dst}` is a unique reference") - } - // Already reported by rustc - rustc_transmute::Reason::TypeError => { - return GetSafeTransmuteErrorAndReason::Silent; - } - rustc_transmute::Reason::SrcLayoutUnknown => { - format!("`{src}` has an unknown layout") - } - rustc_transmute::Reason::DstLayoutUnknown => { - format!("`{dst}` has an unknown layout") - } - }; - GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation } - } - // Should never get a Yes at this point! We already ran it before, and did not get a Yes. - Answer::Yes => span_bug!( - span, - "Inconsistent rustc_transmute::is_transmutable(...) result, got Yes", - ), - other => span_bug!(span, "Unsupported rustc_transmute::Answer variant: `{other:?}`"), - } - } - - fn add_tuple_trait_message( - &self, - obligation_cause_code: &ObligationCauseCode<'tcx>, - err: &mut Diagnostic, - ) { - match obligation_cause_code { - ObligationCauseCode::RustCall => { - err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); - } - ObligationCauseCode::BindingObligation(def_id, _) - | ObligationCauseCode::ItemObligation(def_id) - if self.tcx.is_fn_trait(*def_id) => - { - err.code(rustc_errors::error_code!(E0059)); - err.set_primary_message(format!( - "type parameter to bare `{}` trait must be a tuple", - self.tcx.def_path_str(*def_id) - )); - } - _ => {} - } - } - - fn try_to_add_help_message( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - is_fn_trait: bool, - suggested: bool, - unsatisfied_const: bool, - ) { - let body_def_id = obligation.cause.body_id; - let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } = - obligation.cause.code() - { - *rhs_span - } else { - span - }; - - // Try to report a help message - if is_fn_trait - && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( - obligation.param_env, - trait_ref.self_ty(), - trait_predicate.skip_binder().polarity, - ) - { - self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); - } else if !trait_ref.has_non_region_infer() - && self.predicate_can_apply(obligation.param_env, *trait_predicate) - { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - self.suggest_restricting_param_bound( - err, - *trait_predicate, - None, - obligation.cause.body_id, - ); - } else if trait_ref.def_id().is_local() - && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() - && !self.tcx.trait_is_auto(trait_ref.def_id()) - && !self.tcx.trait_is_alias(trait_ref.def_id()) - { - err.span_help( - self.tcx.def_span(trait_ref.def_id()), - crate::fluent_generated::trait_selection_trait_has_no_impls, - ); - } else if !suggested && !unsatisfied_const { - // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); - if !self.report_similar_impl_candidates( - &impl_candidates, - trait_ref, - body_def_id, - err, - true, - ) { - self.report_similar_impl_candidates_for_root_obligation( - &obligation, - *trait_predicate, - body_def_id, - err, - ); - } - - self.suggest_convert_to_slice( - err, - obligation, - trait_ref, - impl_candidates.as_slice(), - span, - ); - } - } - - fn add_help_message_for_fn_trait( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - err: &mut Diagnostic, - implemented_kind: ty::ClosureKind, - params: ty::Binder<'tcx, Ty<'tcx>>, - ) { - // If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following - // suggestion to add trait bounds for the type, since we only typically implement - // these traits once. - - // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying - // to implement. - let selected_kind = self - .tcx - .fn_trait_kind_from_def_id(trait_ref.def_id()) - .expect("expected to map DefId to ClosureKind"); - if !implemented_kind.extends(selected_kind) { - err.note(format!( - "`{}` implements `{}`, but it must implement `{}`, which is more general", - trait_ref.skip_binder().self_ty(), - implemented_kind, - selected_kind - )); - } - - // Note any argument mismatches - let given_ty = params.skip_binder(); - let expected_ty = trait_ref.skip_binder().args.type_at(1); - if let ty::Tuple(given) = given_ty.kind() - && let ty::Tuple(expected) = expected_ty.kind() - { - if expected.len() != given.len() { - // Note number of types that were expected and given - err.note( - format!( - "expected a closure taking {} argument{}, but one taking {} argument{} was given", - given.len(), - pluralize!(given.len()), - expected.len(), - pluralize!(expected.len()), - ) - ); - } else if !self.same_type_modulo_infer(given_ty, expected_ty) { - // Print type mismatch - let (expected_args, given_args) = - self.cmp(given_ty, expected_ty); - err.note_expected_found( - &"a closure with arguments", - expected_args, - &"a closure with arguments", - given_args, - ); - } - } - } - - fn maybe_add_note_for_unsatisfied_const( - &self, - _obligation: &PredicateObligation<'tcx>, - _trait_ref: ty::PolyTraitRef<'tcx>, - _trait_predicate: &ty::PolyTraitPredicate<'tcx>, - _err: &mut Diagnostic, - _span: Span, - ) -> UnsatisfiedConst { - let unsatisfied_const = UnsatisfiedConst(false); - // FIXME(effects) - unsatisfied_const - } - - fn report_closure_error( - &self, - obligation: &PredicateObligation<'tcx>, - closure_def_id: DefId, - found_kind: ty::ClosureKind, - kind: ty::ClosureKind, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let closure_span = self.tcx.def_span(closure_def_id); - - let mut err = ClosureKindMismatch { - closure_span, - expected: kind, - found: found_kind, - cause_span: obligation.cause.span, - fn_once_label: None, - fn_mut_label: None, - }; - - // Additional context information explaining why the closure only implements - // a particular trait. - if let Some(typeck_results) = &self.typeck_results { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); - match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) { - (ty::ClosureKind::FnOnce, Some((span, place))) => { - err.fn_once_label = Some(ClosureFnOnceLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, &place), - }) - } - (ty::ClosureKind::FnMut, Some((span, place))) => { - err.fn_mut_label = Some(ClosureFnMutLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, &place), - }) - } - _ => {} - } - } - - self.tcx.sess.create_err(err) - } - - fn report_type_parameter_mismatch_cyclic_type_error( - &self, - obligation: &PredicateObligation<'tcx>, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let self_ty = found_trait_ref.self_ty().skip_binder(); - let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() { - ( - ObligationCause::dummy_with_span(self.tcx.def_span(def_id)), - TypeError::CyclicTy(self_ty), - ) - } else { - (obligation.cause.clone(), terr) - }; - self.report_and_explain_type_error( - TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref), - terr, - ) - } - - 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>, - span: Span, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option> { - let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); - let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); - - if expected_trait_ref.self_ty().references_error() { - return None; - } - - let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else { - return None; - }; - - let found_did = match *found_trait_ty.kind() { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Generator(did, ..) => { - Some(did) - } - ty::Adt(def, _) => Some(def.did()), - _ => None, - }; - - let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did)); - let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did)); - - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { - // We check closures twice, with obligations flowing in different directions, - // but we want to complain about them only once. - return None; - } - - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); - - let mut not_tupled = false; - - let found = match found_trait_ref.skip_binder().args.type_at(1).kind() { - ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], - _ => { - not_tupled = true; - vec![ArgKind::empty()] - } - }; - - let expected_ty = expected_trait_ref.skip_binder().args.type_at(1); - let expected = match expected_ty.kind() { - ty::Tuple(ref tys) => { - tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect() - } - _ => { - not_tupled = true; - vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())] - } - }; - - // If this is a `Fn` family trait and either the expected or found - // is not tupled, then fall back to just a regular mismatch error. - // This shouldn't be common unless manually implementing one of the - // traits manually, but don't make it more confusing when it does - // happen. - Some( - if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().gen_trait() && not_tupled - { - self.report_and_explain_type_error( - TypeTrace::poly_trait_refs( - &obligation.cause, - true, - expected_trait_ref, - found_trait_ref, - ), - ty::error::TypeError::Mismatch, - ) - } else if found.len() == expected.len() { - self.report_closure_arg_mismatch( - span, - found_span, - found_trait_ref, - expected_trait_ref, - obligation.cause.code(), - found_node, - obligation.param_env, - ) - } else { - let (closure_span, closure_arg_span, found) = found_did - .and_then(|did| { - let node = self.tcx.hir().get_if_local(did)?; - let (found_span, closure_arg_span, found) = - self.get_fn_like_arguments(node)?; - Some((Some(found_span), closure_arg_span, found)) - }) - .unwrap_or((found_span, None, found)); - - self.report_arg_count_mismatch( - span, - closure_span, - expected, - found, - found_trait_ty.is_closure(), - closure_arg_span, - ) - }, - ) - } - - fn report_not_const_evaluatable_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - ) -> Option> { - if !self.tcx.features().generic_const_exprs { - let mut err = self - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - // - // Note that with `feature(generic_const_exprs)` this case should not - // be reachable. - err.note("this may fail depending on what value the parameter takes"); - err.emit(); - return None; - } - - match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { - let ty::ConstKind::Unevaluated(uv) = ct.kind() else { - bug!("const evaluatable failed for non-unevaluated const `{ct:?}`"); - }; - let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); - let const_span = self.tcx.def_span(uv.def); - match self.tcx.sess.source_map().span_to_snippet(const_span) { - Ok(snippet) => err.help(format!( - "try adding a `where` bound using this expression: `where [(); {snippet}]:`" - )), - _ => err.help("consider adding a `where` bound using this expression"), - }; - Some(err) - } - _ => { - span_bug!( - span, - "unexpected non-ConstEvaluatable predicate, this should not be reachable" - ) - } - } - } -} - struct UnsatisfiedConst(pub bool); -fn get_explanation_based_on_obligation<'tcx>( - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - pre_message: String, -) -> String { - if let ObligationCauseCode::MainFunctionType = obligation.cause.code() { - "consider using `()`, or a `Result`".to_owned() - } else { - let ty_desc = match trait_ref.skip_binder().self_ty().kind() { - ty::FnDef(_, _) => Some("fn item"), - ty::Closure(_, _) => Some("closure"), - _ => None, - }; - - match ty_desc { - Some(desc) => format!( - "{}the trait `{}` is not implemented for {} `{}`", - pre_message, - trait_predicate.print_modifiers_and_trait_path(), - desc, - trait_ref.skip_binder().self_ty(), - ), - None => format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_predicate.print_modifiers_and_trait_path(), - trait_ref.skip_binder().self_ty(), - ), - } - } -} /// Crude way of getting back an `Expr` from a `Span`. pub struct FindExprBySpan<'hir> { pub span: Span, 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 4086db2ab5578..d9059e46a8c55 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 @@ -18,7 +18,7 @@ use crate::errors::{ EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, }; -use super::InferCtxtPrivExt; +use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; pub trait TypeErrCtxtExt<'tcx> { /*private*/ @@ -104,7 +104,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => { self.describe_generator(*body_id).or_else(|| { Some(match sig.header { - hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async function", + hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => { + "an async function" + } _ => "a function", }) }) @@ -118,7 +120,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .. }) => self.describe_generator(*body_id).or_else(|| { Some(match sig.header { - hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async method", + hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method", _ => "a method", }) }), 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 a08ebe5a9ea8d..9aebe77a10481 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -30,10 +30,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTi use rustc_middle::hir::map; use rustc_middle::ty::error::TypeError::{self, Sorts}; use rustc_middle::ty::{ - self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, GenericArgs, InferTy, IsSuggestable, - ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, TypeckResults, + self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs, + InferTy, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, TypeckResults, }; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -42,15 +41,15 @@ use rustc_target::spec::abi; use std::borrow::Cow; use std::iter; -use super::InferCtxtPrivExt; use crate::infer::InferCtxtExt as _; +use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; #[derive(Debug)] pub enum GeneratorInteriorOrUpvar { // span of interior type - Interior(Span, Option<(Option, Span, Option, Option)>), + Interior(Span, Option<(Span, Option)>), // span of upvar Upvar(Span), } @@ -58,15 +57,12 @@ pub enum GeneratorInteriorOrUpvar { // This type provides a uniform interface to retrieve data on generators, whether it originated from // the local crate being compiled or from a foreign crate. #[derive(Debug)] -pub enum GeneratorData<'tcx, 'a> { - Local(&'a TypeckResults<'tcx>), - Foreign(&'tcx GeneratorDiagnosticData<'tcx>), -} +struct GeneratorData<'tcx, 'a>(&'a TypeckResults<'tcx>); impl<'tcx, 'a> GeneratorData<'tcx, 'a> { - // Try to get information about variables captured by the generator that matches a type we are - // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to - // meet an obligation + /// Try to get information about variables captured by the generator that matches a type we are + /// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to + /// meet an obligation fn try_get_upvar_span( &self, infer_context: &InferCtxt<'tcx>, @@ -76,27 +72,21 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> { where F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool, { - match self { - GeneratorData::Local(typeck_results) => { - infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| { - upvars.iter().find_map(|(upvar_id, upvar)| { - let upvar_ty = typeck_results.node_type(*upvar_id); - let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty); - ty_matches(ty::Binder::dummy(upvar_ty)) - .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span)) - }) - }) - } - GeneratorData::Foreign(_) => None, - } + infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| { + upvars.iter().find_map(|(upvar_id, upvar)| { + let upvar_ty = self.0.node_type(*upvar_id); + let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty); + ty_matches(ty::Binder::dummy(upvar_ty)) + .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span)) + }) + }) } - // Try to get the span of a type being awaited on that matches the type we are looking with the - // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an - // obligation + /// Try to get the span of a type being awaited on that matches the type we are looking with the + /// `ty_matches` function. We uses it to find awaited type which causes a failure to meet an + /// obligation fn get_from_await_ty( &self, - tcx: TyCtxt<'tcx>, visitor: AwaitsVisitor, hir: map::Map<'tcx>, ty_matches: F, @@ -104,69 +94,12 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> { where F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool, { - match self { - GeneratorData::Local(typeck_results) => visitor - .awaits - .into_iter() - .map(|id| hir.expect_expr(id)) - .find(|await_expr| { - ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr))) - }) - .map(|expr| expr.span), - GeneratorData::Foreign(generator_diagnostic_data) => visitor - .awaits - .into_iter() - .map(|id| hir.expect_expr(id)) - .find(|await_expr| { - ty_matches(ty::Binder::dummy( - generator_diagnostic_data - .adjustments - .get(&await_expr.hir_id.local_id) - .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..]) - .last() - .map_or_else::, _, _>( - || { - generator_diagnostic_data - .nodes_types - .get(&await_expr.hir_id.local_id) - .cloned() - .unwrap_or_else(|| { - bug!( - "node_type: no type for node {}", - tcx.hir().node_to_string(await_expr.hir_id) - ) - }) - }, - |adj| adj.target, - ), - )) - }) - .map(|expr| expr.span), - } - } - - /// Get the type, expression, span and optional scope span of all types - /// that are live across the yield of this generator - fn get_generator_interior_types( - &self, - ) -> ty::Binder<'tcx, &[GeneratorInteriorTypeCause<'tcx>]> { - match self { - GeneratorData::Local(typeck_result) => { - typeck_result.generator_interior_types.as_deref() - } - GeneratorData::Foreign(generator_diagnostic_data) => { - generator_diagnostic_data.generator_interior_types.as_deref() - } - } - } - - // Used to get the source of the data, note we don't have as much information for generators - // originated from foreign crates - fn is_foreign(&self) -> bool { - match self { - GeneratorData::Local(_) => false, - GeneratorData::Foreign(_) => true, - } + visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(&await_expr)))) + .map(|expr| expr.span) } } @@ -316,7 +249,6 @@ pub trait TypeErrCtxtExt<'tcx> { outer_generator: Option, trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, - typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, ); @@ -414,6 +346,12 @@ pub trait TypeErrCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, cause: &ObligationCause<'tcx>, ); + + fn suggest_desugaring_async_fn_in_trait( + &self, + err: &mut Diagnostic, + trait_ref: ty::PolyTraitRef<'tcx>, + ); } fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { @@ -2234,11 +2172,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); match *ty.kind() { - ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, _) => { + ty::Generator(did, ..) | ty::GeneratorWitness(did, _) => { generator = generator.or(Some(did)); outer_generator = Some(did); } - ty::GeneratorWitness(..) => {} ty::Tuple(_) if !seen_upvar_tys_infer_tuple => { // By introducing a tuple of upvar types into the chain of obligations // of a generator, the first non-generator item is now the tuple itself, @@ -2264,11 +2201,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); match *ty.kind() { - ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, ..) => { + ty::Generator(did, ..) | ty::GeneratorWitness(did, ..) => { generator = generator.or(Some(did)); outer_generator = Some(did); } - ty::GeneratorWitness(..) => {} ty::Tuple(_) if !seen_upvar_tys_infer_tuple => { // By introducing a tuple of upvar types into the chain of obligations // of a generator, the first non-generator item is now the tuple itself, @@ -2345,12 +2281,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // cycles. If we can't use resolved types because the generator comes from another crate, // we still provide a targeted error but without all the relevant spans. let generator_data = match &self.typeck_results { - Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData::Local(&t), + Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData(&t), _ if generator_did.is_local() => { - GeneratorData::Local(self.tcx.typeck(generator_did.expect_local())) - } - _ if let Some(generator_diag_data) = self.tcx.generator_diagnostic_data(generator_did) => { - GeneratorData::Foreign(generator_diag_data) + GeneratorData(self.tcx.typeck(generator_did.expect_local())) } _ => return false, }; @@ -2362,30 +2295,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut interior_or_upvar_span = None; - let from_awaited_ty = generator_data.get_from_await_ty(self.tcx, visitor, hir, ty_matches); + let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches); debug!(?from_awaited_ty); - // The generator interior types share the same binders - if let Some(cause) = - generator_data.get_generator_interior_types().skip_binder().iter().find( - |ty::GeneratorInteriorTypeCause { ty, .. }| { - ty_matches(generator_data.get_generator_interior_types().rebind(*ty)) - }, - ) - { - let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause; - - interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior( - *span, - Some((*scope_span, *yield_span, *expr, from_awaited_ty)), - )); - - if interior_or_upvar_span.is_none() && generator_data.is_foreign() { - interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span, None)); - } - } else if self.tcx.sess.opts.unstable_opts.drop_tracking_mir - // Avoid disclosing internal information to downstream crates. - && generator_did.is_local() + // Avoid disclosing internal information to downstream crates. + if generator_did.is_local() // Try to avoid cycles. && !generator_within_in_progress_typeck && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did) @@ -2401,7 +2315,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits { interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior( decl.source_info.span, - Some((None, source_info.span, None, from_awaited_ty)), + Some((source_info.span, from_awaited_ty)), )); break 'find_source; } @@ -2414,17 +2328,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { generator_data.try_get_upvar_span(&self, generator_did, ty_matches); } - if interior_or_upvar_span.is_none() && generator_data.is_foreign() { + if interior_or_upvar_span.is_none() && !generator_did.is_local() { interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None)); } debug!(?interior_or_upvar_span); if let Some(interior_or_upvar_span) = interior_or_upvar_span { let is_async = self.tcx.generator_is_async(generator_did); - let typeck_results = match generator_data { - GeneratorData::Local(typeck_results) => Some(typeck_results), - GeneratorData::Foreign(_) => None, - }; self.note_obligation_cause_for_async_await( err, interior_or_upvar_span, @@ -2432,7 +2342,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { outer_generator, trait_ref, target_ty, - typeck_results, obligation, next_code, ); @@ -2453,7 +2362,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { outer_generator: Option, trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, - typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, ) { @@ -2511,9 +2419,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path()) }; - let mut explain_yield = |interior_span: Span, - yield_span: Span, - scope_span: Option| { + let mut explain_yield = |interior_span: Span, yield_span: Span| { let mut span = MultiSpan::from_span(yield_span); let snippet = match source_map.span_to_snippet(interior_span) { // #70935: If snippet contains newlines, display "the value" instead @@ -2545,22 +2451,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { interior_span, format!("has type `{target_ty}` which {trait_explanation}"), ); - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - - let msg = format!("{snippet} is later dropped here"); - span.push_span_label(scope_span, msg); - } err.span_note( - span, - format!( - "{future_or_generator} {trait_explanation} as this value is used across {an_await_or_yield}" - ), - ); + span, + format!("{future_or_generator} {trait_explanation} as this value is used across {an_await_or_yield}"), + ); }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => { - if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { + if let Some((yield_span, from_awaited_ty)) = interior_extra_info { if let Some(await_span) = from_awaited_ty { // The type causing this obligation is one being awaited at await_span. let mut span = MultiSpan::from_span(await_span); @@ -2578,62 +2476,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } else { // Look at the last interior type to get a span for the `.await`. - debug!( - generator_interior_types = ?format_args!( - "{:#?}", typeck_results.as_ref().map(|t| &t.generator_interior_types) - ), - ); - explain_yield(interior_span, yield_span, scope_span); - } - - if let Some(expr_id) = expr { - let expr = hir.expect_expr(expr_id); - debug!("target_ty evaluated from {:?}", expr); - - let parent = hir.parent_id(expr_id); - if let Some(hir::Node::Expr(e)) = hir.find(parent) { - let parent_span = hir.span(parent); - let parent_did = parent.owner.to_def_id(); - // ```rust - // impl T { - // fn foo(&self) -> i32 {} - // } - // T.foo(); - // ^^^^^^^ a temporary `&T` created inside this method call due to `&self` - // ``` - // - let is_region_borrow = if let Some(typeck_results) = typeck_results { - typeck_results - .expr_adjustments(expr) - .iter() - .any(|adj| adj.is_region_borrow()) - } else { - false - }; - - // ```rust - // struct Foo(*const u8); - // bar(Foo(std::ptr::null())).await; - // ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor. - // ``` - debug!(parent_def_kind = ?self.tcx.def_kind(parent_did)); - let is_raw_borrow_inside_fn_like_call = - match self.tcx.def_kind(parent_did) { - DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(), - _ => false, - }; - if let Some(typeck_results) = typeck_results { - if (typeck_results.is_method_call(e) && is_region_borrow) - || is_raw_borrow_inside_fn_like_call - { - err.span_help( - parent_span, - "consider moving this into a `let` \ - binding to create a shorter lived borrow", - ); - } - } - } + explain_yield(interior_span, yield_span); } } } @@ -2711,6 +2554,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::IfExpressionWithNoElse | ObligationCauseCode::MainFunctionType | ObligationCauseCode::StartFunctionType + | ObligationCauseCode::LangFunctionType(_) | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression @@ -3000,6 +2844,24 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::InlineAsmSized => { err.note("all inline asm arguments must have a statically known size"); } + ObligationCauseCode::SizedClosureCapture(closure_def_id) => { + err.note("all values captured by value by a closure must have a statically known size"); + let hir::ExprKind::Closure(closure) = self.tcx.hir().get_by_def_id(closure_def_id).expect_expr().kind else { + bug!("expected closure in SizedClosureCapture obligation"); + }; + if let hir::CaptureBy::Value = closure.capture_clause + && let Some(span) = closure.fn_arg_span + { + err.span_label(span, "this closure captures all values by move"); + } + } + ObligationCauseCode::SizedGeneratorInterior(generator_def_id) => { + let what = match self.tcx.generator_kind(generator_def_id) { + None | Some(hir::GeneratorKind::Gen) => "yield", + Some(hir::GeneratorKind::Async(..)) => "await", + }; + err.note(format!("all values live across `{what}` must have a statically known size")); + } ObligationCauseCode::ConstPatternStructural => { err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`"); } @@ -3065,20 +2927,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } err.span_note(self.tcx.def_span(def_id), msg) } - ty::GeneratorWitness(bound_tys) => { - use std::fmt::Write; - - // FIXME: this is kind of an unusual format for rustc, can we make it more clear? - // Maybe we should just remove this note altogether? - // FIXME: only print types which don't meet the trait requirement - let mut msg = - "required because it captures the following types: ".to_owned(); - for ty in bound_tys.skip_binder() { - with_forced_trimmed_paths!(write!(msg, "`{ty}`, ").unwrap()); - } - err.note(msg.trim_end_matches(", ").to_string()) - } - ty::GeneratorWitnessMIR(def_id, args) => { + ty::GeneratorWitness(def_id, args) => { use std::fmt::Write; // FIXME: this is kind of an unusual format for rustc, can we make it more clear? @@ -4100,6 +3949,90 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }); } } + + fn suggest_desugaring_async_fn_in_trait( + &self, + err: &mut Diagnostic, + trait_ref: ty::PolyTraitRef<'tcx>, + ) { + // Don't suggest if RTN is active -- we should prefer a where-clause bound instead. + if self.tcx.features().return_type_notation { + return; + } + + let trait_def_id = trait_ref.def_id(); + + // Only suggest specifying auto traits + if !self.tcx.trait_is_auto(trait_def_id) { + return; + } + + // Look for an RPITIT + let ty::Alias(ty::Projection, alias_ty) = trait_ref.self_ty().skip_binder().kind() else { + return; + }; + let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = + self.tcx.opt_rpitit_info(alias_ty.def_id) + else { + return; + }; + + let auto_trait = self.tcx.def_path_str(trait_def_id); + // ... which is a local function + let Some(fn_def_id) = fn_def_id.as_local() else { + // If it's not local, we can at least mention that the method is async, if it is. + if self.tcx.asyncness(fn_def_id).is_async() { + err.span_note( + self.tcx.def_span(fn_def_id), + format!( + "`{}::{}` is an `async fn` in trait, which does not \ + automatically imply that its future is `{auto_trait}`", + alias_ty.trait_ref(self.tcx), + self.tcx.item_name(fn_def_id) + ), + ); + } + return; + }; + let Some(hir::Node::TraitItem(item)) = self.tcx.hir().find_by_def_id(fn_def_id) else { + return; + }; + + // ... whose signature is `async` (i.e. this is an AFIT) + let (sig, body) = item.expect_fn(); + let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) = + sig.decl.output + else { + // This should never happen, but let's not ICE. + return; + }; + + // Check that this is *not* a nested `impl Future` RPIT in an async fn + // (i.e. `async fn foo() -> impl Future`) + if def.owner_id.to_def_id() != opaque_def_id { + return; + } + + let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait( + self.tcx, + *sig, + *body, + opaque_def_id.expect_local(), + &format!(" + {auto_trait}"), + ) else { + return; + }; + + let function_name = self.tcx.def_path_str(fn_def_id); + err.multipart_suggestion( + format!( + "`{auto_trait}` can be made part of the associated future's \ + guarantees for all implementations of `{function_name}`" + ), + sugg, + Applicability::MachineApplicable, + ); + } } /// Add a hint to add a missing borrow or remove an unnecessary one. @@ -4321,6 +4254,39 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> { } } +pub(super) fn get_explanation_based_on_obligation<'tcx>( + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + pre_message: String, +) -> String { + if let ObligationCauseCode::MainFunctionType = obligation.cause.code() { + "consider using `()`, or a `Result`".to_owned() + } else { + let ty_desc = match trait_ref.skip_binder().self_ty().kind() { + ty::FnDef(_, _) => Some("fn item"), + ty::Closure(_, _) => Some("closure"), + _ => None, + }; + + match ty_desc { + Some(desc) => format!( + "{}the trait `{}` is not implemented for {} `{}`", + pre_message, + trait_predicate.print_modifiers_and_trait_path(), + desc, + trait_ref.skip_binder().self_ty(), + ), + None => format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_predicate.print_modifiers_and_trait_path(), + trait_ref.skip_binder().self_ty(), + ), + } + } +} + // Replace `param` with `replace_ty` struct ReplaceImplTraitFolder<'tcx> { tcx: TyCtxt<'tcx>, @@ -4342,3 +4308,65 @@ impl<'tcx> TypeFolder> for ReplaceImplTraitFolder<'tcx> { self.tcx } } + +pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( + tcx: TyCtxt<'tcx>, + sig: hir::FnSig<'tcx>, + body: hir::TraitFn<'tcx>, + opaque_def_id: LocalDefId, + add_bounds: &str, +) -> Option> { + let hir::IsAsync::Async(async_span) = sig.header.asyncness else { + return None; + }; + let Ok(async_span) = tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace()) + else { + return None; + }; + + let future = tcx.hir().get_by_def_id(opaque_def_id).expect_item().expect_opaque_ty(); + let Some(hir::GenericBound::LangItemTrait(_, _, _, generics)) = future.bounds.get(0) else { + // `async fn` should always lower to a lang item bound... but don't ICE. + return None; + }; + let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) = + generics.bindings.get(0).map(|binding| binding.kind) + else { + // Also should never happen. + return None; + }; + + let mut sugg = if future_output_ty.span.is_empty() { + vec![ + (async_span, String::new()), + ( + future_output_ty.span, + format!(" -> impl std::future::Future{add_bounds}"), + ), + ] + } else { + vec![ + (future_output_ty.span.shrink_to_lo(), "impl std::future::Future{add_bounds}")), + (async_span, String::new()), + ] + }; + + // If there's a body, we also need to wrap it in `async {}` + if let hir::TraitFn::Provided(body) = body { + let body = tcx.hir().body(body); + let body_span = body.value.span; + let body_span_without_braces = + body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1)); + if body_span_without_braces.is_empty() { + sugg.push((body_span_without_braces, " async {} ".to_owned())); + } else { + sugg.extend([ + (body_span_without_braces.shrink_to_lo(), "async {".to_owned()), + (body_span_without_braces.shrink_to_hi(), "} ".to_owned()), + ]); + } + } + + Some(sugg) +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs new file mode 100644 index 0000000000000..8adfb27a3f448 --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -0,0 +1,3241 @@ +use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _}; +use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _}; +use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch}; +use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::{self, InferCtxt}; +use crate::traits::error_reporting::infer_ctxt_ext::InferCtxtExt; +use crate::traits::error_reporting::{ambiguity, ambiguity::Ambiguity::*}; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use crate::traits::specialize::to_pretty_impl_header; +use crate::traits::NormalizeExt; +use crate::traits::{ + elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, + ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionError, TraitNotObjectSafe, +}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_errors::{ + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, Style, +}; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, Namespace, Res}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; +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::{DefiningAnchor, SelectionOutputTypeParameterMismatch}; +use rustc_middle::ty::abstract_const::NotConstEvaluatable; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; +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::{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::iter; + +use super::{ + dump_proof_tree, ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam, + GetSafeTransmuteErrorAndReason, HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst, +}; + +pub use rustc_infer::traits::error_reporting::*; + +pub trait TypeErrCtxtExt<'tcx> { + fn build_overflow_error( + &self, + predicate: &T, + span: Span, + suggest_increasing_limit: bool, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> + where + T: fmt::Display + + TypeFoldable> + + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + >>::Error: std::fmt::Debug; + + fn report_overflow_error( + &self, + predicate: &T, + span: Span, + suggest_increasing_limit: bool, + mutate: impl FnOnce(&mut Diagnostic), + ) -> ! + where + T: fmt::Display + + TypeFoldable> + + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + >>::Error: std::fmt::Debug; + + fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; + + fn report_fulfillment_errors(&self, errors: Vec>) -> ErrorGuaranteed; + + fn report_overflow_obligation( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: ToPredicate<'tcx> + Clone; + + fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); + + fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; + + /// The `root_obligation` parameter should be the `root_obligation` field + /// from a `FulfillmentError`. If no `FulfillmentError` is available, + /// then it should be the same as `obligation`. + fn report_selection_error( + &self, + obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'tcx>, + error: &SelectionError<'tcx>, + ); + + fn report_const_param_not_wf( + &self, + ty: Ty<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; +} + +impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { + fn report_fulfillment_errors( + &self, + mut errors: Vec>, + ) -> ErrorGuaranteed { + #[derive(Debug)] + struct ErrorDescriptor<'tcx> { + predicate: ty::Predicate<'tcx>, + index: Option, // None if this is an old error + } + + let mut error_map: FxIndexMap<_, Vec<_>> = self + .reported_trait_errors + .borrow() + .iter() + .map(|(&span, predicates)| { + ( + span, + predicates + .iter() + .map(|&predicate| ErrorDescriptor { predicate, index: None }) + .collect(), + ) + }) + .collect(); + + // Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics + // with more relevant type information and hide redundant E0282 errors. + errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) + if Some(pred.def_id()) == self.tcx.lang_items().sized_trait() => + { + 1 + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3, + ty::PredicateKind::Coerce(_) => 2, + _ => 0, + }); + + for (index, error) in errors.iter().enumerate() { + // We want to ignore desugarings here: spans are equivalent even + // if one is the result of a desugaring and the other is not. + let mut span = error.obligation.cause.span; + let expn_data = span.ctxt().outer_expn_data(); + if let ExpnKind::Desugaring(_) = expn_data.kind { + span = expn_data.call_site; + } + + error_map.entry(span).or_default().push(ErrorDescriptor { + predicate: error.obligation.predicate, + index: Some(index), + }); + + self.reported_trait_errors + .borrow_mut() + .entry(span) + .or_default() + .push(error.obligation.predicate); + } + + // We do this in 2 passes because we want to display errors in order, though + // maybe it *is* better to sort errors by span or something. + let mut is_suppressed = vec![false; errors.len()]; + for (_, error_set) in error_map.iter() { + // We want to suppress "duplicate" errors with the same span. + for error in error_set { + if let Some(index) = error.index { + // Suppress errors that are either: + // 1) strictly implied by another error. + // 2) implied by an error with a smaller index. + for error2 in error_set { + if error2.index.is_some_and(|index2| is_suppressed[index2]) { + // Avoid errors being suppressed by already-suppressed + // errors, to prevent all errors from being suppressed + // at once. + continue; + } + + if self.error_implies(error2.predicate, error.predicate) + && !(error2.index >= error.index + && self.error_implies(error.predicate, error2.predicate)) + { + info!("skipping {:?} (implied by {:?})", error, error2); + is_suppressed[index] = true; + break; + } + } + } + } + } + + for from_expansion in [false, true] { + for (error, suppressed) in iter::zip(&errors, &is_suppressed) { + if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { + self.report_fulfillment_error(error); + } + } + } + + self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors") + } + + /// Reports that an overflow has occurred and halts compilation. We + /// halt compilation unconditionally because it is important that + /// overflows never be masked -- they basically represent computations + /// whose result could not be truly determined and thus we can't say + /// if the program type checks or not -- and they are unusual + /// occurrences in any case. + fn report_overflow_error( + &self, + predicate: &T, + span: Span, + suggest_increasing_limit: bool, + mutate: impl FnOnce(&mut Diagnostic), + ) -> ! + where + T: fmt::Display + + TypeFoldable> + + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + >>::Error: std::fmt::Debug, + { + let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); + mutate(&mut err); + err.emit(); + + self.tcx.sess.abort_if_errors(); + bug!(); + } + + fn build_overflow_error( + &self, + predicate: &T, + span: Span, + suggest_increasing_limit: bool, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> + where + T: fmt::Display + + TypeFoldable> + + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, + >>::Error: std::fmt::Debug, + { + let predicate = self.resolve_vars_if_possible(predicate.clone()); + let mut pred_str = predicate.to_string(); + + if pred_str.len() > 50 { + // We don't need to save the type to a file, we will be talking about this type already + // in a separate note when we explain the obligation, so it will be available that way. + pred_str = predicate + .print(FmtPrinter::new_with_limit( + self.tcx, + Namespace::TypeNS, + rustc_session::Limit(6), + )) + .unwrap() + .into_buffer(); + } + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0275, + "overflow evaluating the requirement `{}`", + pred_str, + ); + + if suggest_increasing_limit { + self.suggest_new_overflow_limit(&mut err); + } + + err + } + + /// Reports that an overflow has occurred and halts compilation. We + /// halt compilation unconditionally because it is important that + /// overflows never be masked -- they basically represent computations + /// whose result could not be truly determined and thus we can't say + /// if the program type checks or not -- and they are unusual + /// occurrences in any case. + fn report_overflow_obligation( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: ToPredicate<'tcx> + Clone, + { + let predicate = obligation.predicate.clone().to_predicate(self.tcx); + let predicate = self.resolve_vars_if_possible(predicate); + self.report_overflow_error( + &predicate, + obligation.cause.span, + suggest_increasing_limit, + |err| { + self.note_obligation_cause_code( + obligation.cause.body_id, + err, + predicate, + obligation.param_env, + obligation.cause.code(), + &mut vec![], + &mut Default::default(), + ); + }, + ); + } + + fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) { + let suggested_limit = match self.tcx.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; + err.help(format!( + "consider increasing the recursion limit by adding a \ + `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", + suggested_limit, + self.tcx.crate_name(LOCAL_CRATE), + )); + } + + /// Reports that a cycle was detected which led to overflow and halts + /// compilation. This is equivalent to `report_overflow_obligation` except + /// that we can give a more helpful error message (and, in particular, + /// we do not suggest increasing the overflow limit, which is not + /// going to help). + fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { + let cycle = self.resolve_vars_if_possible(cycle.to_owned()); + assert!(!cycle.is_empty()); + + debug!(?cycle, "report_overflow_error_cycle"); + + // The 'deepest' obligation is most likely to have a useful + // cause 'backtrace' + self.report_overflow_obligation( + cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), + false, + ); + } + + fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed { + let obligation = self.resolve_vars_if_possible(obligation); + let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true); + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + err.emit() + } + + fn report_selection_error( + &self, + mut obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'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( + tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"), + ); + + let mut err = match *error { + SelectionError::Unimplemented => { + // If this obligation was generated as a result of well-formedness checking, see if we + // can get a better error message by performing HIR-based well-formedness checking. + if let ObligationCauseCode::WellFormed(Some(wf_loc)) = + root_obligation.cause.code().peel_derives() + && !obligation.predicate.has_non_region_infer() + { + if let Some(cause) = self + .tcx + .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc)) + { + obligation.cause = cause.clone(); + span = obligation.cause.span; + } + } + + if let ObligationCauseCode::CompareImplItemObligation { + impl_item_def_id, + trait_item_def_id, + kind: _, + } = *obligation.cause.code() + { + self.report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{}`", obligation.predicate), + ) + .emit(); + return; + } + + // Report a const-param specific error + if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() + { + self.report_const_param_not_wf(ty, &obligation).emit(); + return; + } + + let bound_predicate = obligation.predicate.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { + let trait_predicate = bound_predicate.rebind(trait_predicate); + let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + + // FIXME(effects) + let predicate_is_const = false; + + if self.tcx.sess.has_errors().is_some() + && trait_predicate.references_error() + { + return; + } + let trait_ref = trait_predicate.to_poly_trait_ref(); + + let (post_message, pre_message, type_def) = self + .get_parent_trait_ref(obligation.cause.code()) + .map(|(t, s)| { + ( + format!(" in `{t}`"), + format!("within `{t}`, "), + s.map(|s| (format!("within this `{t}`"), s)), + ) + }) + .unwrap_or_default(); + + let OnUnimplementedNote { + message, + label, + note, + parent_label, + append_const_msg, + } = self.on_unimplemented_note(trait_ref, &obligation); + let have_alt_message = message.is_some() || label.is_some(); + let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); + let is_unsize = + Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); + let (message, note, append_const_msg) = if is_try_conversion { + ( + Some(format!( + "`?` couldn't convert the error to `{}`", + trait_ref.skip_binder().self_ty(), + )), + Some( + "the question mark operation (`?`) implicitly performs a \ + conversion on the error value using the `From` trait" + .to_owned(), + ), + Some(AppendConstMessage::Default), + ) + } else { + (message, note, append_const_msg) + }; + + let err_msg = self.get_standard_error_message( + &trait_predicate, + message, + predicate_is_const, + append_const_msg, + post_message, + ); + + let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id()) + == self.tcx.lang_items().transmute_trait() + { + // Recompute the safe transmute reason and use that for the error reporting + match self.get_safe_transmute_error_and_reason( + obligation.clone(), + trait_ref, + span, + ) { + GetSafeTransmuteErrorAndReason::Silent => return, + GetSafeTransmuteErrorAndReason::Error { + err_msg, + safe_transmute_explanation, + } => (err_msg, Some(safe_transmute_explanation)), + } + } else { + (err_msg, None) + }; + + let mut err = struct_span_err!(self.tcx.sess, span, E0277, "{}", err_msg); + + if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { + err.span_label( + ret_span, + format!( + "expected `{}` because of this", + trait_ref.skip_binder().self_ty() + ), + ); + } + + if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { + self.add_tuple_trait_message( + &obligation.cause.code().peel_derives(), + &mut err, + ); + } + + if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() + && predicate_is_const + { + err.note("`~const Drop` was renamed to `~const Destruct`"); + err.note("See for more details"); + } + + let explanation = get_explanation_based_on_obligation( + &obligation, + trait_ref, + &trait_predicate, + pre_message, + ); + + self.check_for_binding_assigned_block_without_tail_expression( + &obligation, + &mut err, + trait_predicate, + ); + if self.suggest_add_reference_to_arg( + &obligation, + &mut err, + trait_predicate, + have_alt_message, + ) { + self.note_obligation_cause(&mut err, &obligation); + err.emit(); + return; + } + if let Some(s) = label { + // If it has a custom `#[rustc_on_unimplemented]` + // error message, let's display it as the label! + err.span_label(span, s); + if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { + // When the self type is a type param We don't need to "the trait + // `std::marker::Sized` is not implemented for `T`" as we will point + // at the type param with a label to suggest constraining it. + err.help(explanation); + } + } else if let Some(custom_explanation) = safe_transmute_explanation { + err.span_label(span, custom_explanation); + } else { + err.span_label(span, explanation); + } + + if let ObligationCauseCode::Coercion { source, target } = + *obligation.cause.code().peel_derives() + { + if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + self.suggest_borrowing_for_object_cast( + &mut err, + &root_obligation, + source, + target, + ); + } + } + + let UnsatisfiedConst(unsatisfied_const) = self + .maybe_add_note_for_unsatisfied_const( + &obligation, + trait_ref, + &trait_predicate, + &mut err, + span, + ); + + if let Some((msg, span)) = type_def { + err.span_label(span, msg); + } + if let Some(s) = note { + // If it has a custom `#[rustc_on_unimplemented]` note, let's display it + err.note(s); + } + if let Some(s) = parent_label { + let body = obligation.cause.body_id; + err.span_label(tcx.def_span(body), s); + } + + self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); + self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); + let mut suggested = + self.suggest_dereferences(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); + let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + suggested = if let &[cand] = &impl_candidates[..] { + let cand = cand.trait_ref; + if let (ty::FnPtr(_), ty::FnDef(..)) = + (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) + { + err.span_suggestion( + span.shrink_to_hi(), + format!( + "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`", + cand.print_only_trait_path(), + cand.self_ty(), + ), + format!(" as {}", cand.self_ty()), + Applicability::MaybeIncorrect, + ); + true + } else { + false + } + } else { + false + } || suggested; + suggested |= + self.suggest_remove_reference(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_semicolon_removal( + &obligation, + &mut err, + span, + trait_predicate, + ); + self.note_version_mismatch(&mut err, &trait_ref); + self.suggest_remove_await(&obligation, &mut err); + self.suggest_derive(&obligation, &mut err, trait_predicate); + + if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { + self.suggest_await_before_try( + &mut err, + &obligation, + trait_predicate, + span, + ); + } + + if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { + err.emit(); + return; + } + + if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { + err.emit(); + return; + } + + if is_unsize { + // If the obligation failed due to a missing implementation of the + // `Unsize` trait, give a pointer to why that might be the case + err.note( + "all implementations of `Unsize` are provided \ + automatically by the compiler, see \ + \ + for more information", + ); + } + + let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); + let is_target_feature_fn = if let ty::FnDef(def_id, _) = + *trait_ref.skip_binder().self_ty().kind() + { + !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() + } else { + false + }; + if is_fn_trait && is_target_feature_fn { + err.note( + "`#[target_feature]` functions do not implement the `Fn` traits", + ); + } + + self.try_to_add_help_message( + &obligation, + trait_ref, + &trait_predicate, + &mut err, + span, + is_fn_trait, + suggested, + unsatisfied_const, + ); + + // Changing mutability doesn't make a difference to whether we have + // an `Unsize` impl (Fixes ICE in #71036) + if !is_unsize { + self.suggest_change_mut(&obligation, &mut err, trait_predicate); + } + + // If this error is due to `!: Trait` not implemented but `(): Trait` is + // implemented, and fallback has occurred, then it could be due to a + // variable that used to fallback to `()` now falling back to `!`. Issue a + // note informing about the change in behaviour. + if trait_predicate.skip_binder().self_ty().is_never() + && self.fallback_has_occurred + { + let predicate = trait_predicate.map_bound(|trait_pred| { + 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) { + err.note( + "this error might have been caused by changes to \ + Rust's type-inference algorithm (see issue #48950 \ + \ + for more information)", + ); + err.help("did you intend to use the type `()` here instead?"); + } + } + + self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause); + self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref); + + // Return early if the trait is Debug or Display and the invocation + // originates within a standard library macro, because the output + // is otherwise overwhelming and unhelpful (see #85844 for an + // example). + + let in_std_macro = + match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { + Some(macro_def_id) => { + let crate_name = tcx.crate_name(macro_def_id.krate); + crate_name == sym::std || crate_name == sym::core + } + None => false, + }; + + if in_std_macro + && matches!( + self.tcx.get_diagnostic_name(trait_ref.def_id()), + Some(sym::Debug | sym::Display) + ) + { + err.emit(); + return; + } + + err + } + + ty::PredicateKind::Subtype(predicate) => { + // Errors for Subtype predicates show up as + // `FulfillmentErrorCode::CodeSubtypeError`, + // not selection error. + span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) + } + + ty::PredicateKind::Coerce(predicate) => { + // Errors for Coerce predicates show up as + // `FulfillmentErrorCode::CodeSubtypeError`, + // not selection error. + span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate) + } + + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => { + span_bug!( + span, + "outlives clauses should not error outside borrowck. obligation: `{:?}`", + obligation + ) + } + + ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { + span_bug!( + span, + "projection clauses should be implied from elsewhere. obligation: `{:?}`", + obligation + ) + } + + ty::PredicateKind::ObjectSafe(trait_def_id) => { + let violations = self.tcx.object_safety_violations(trait_def_id); + report_object_safety_error(self.tcx, span, trait_def_id, violations) + } + + ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { + let found_kind = self.closure_kind(closure_args).unwrap(); + self.report_closure_error(&obligation, closure_def_id, found_kind, kind) + } + + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { + let ty = self.resolve_vars_if_possible(ty); + match self.tcx.sess.opts.unstable_opts.trait_solver { + TraitSolver::Classic => { + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); + } + TraitSolver::Next | TraitSolver::NextCoherence => { + // FIXME: we'll need a better message which takes into account + // which bounds actually failed to hold. + self.tcx.sess.struct_span_err( + span, + format!("the type `{ty}` is not well-formed"), + ) + } + } + } + + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { + // Errors for `ConstEvaluatable` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + span_bug!( + span, + "const-evaluatable requirement gave wrong error: `{:?}`", + obligation + ) + } + + ty::PredicateKind::ConstEquate(..) => { + // Errors for `ConstEquate` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + span_bug!( + span, + "const-equate requirement gave wrong error: `{:?}`", + obligation + ) + } + + ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), + + ty::PredicateKind::AliasRelate(..) => span_bug!( + span, + "AliasRelate predicate should never be the predicate cause of a SelectionError" + ), + + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + let mut diag = self.tcx.sess.struct_span_err( + span, + format!("the constant `{ct}` is not of type `{ty}`"), + ); + self.note_type_err( + &mut diag, + &obligation.cause, + None, + None, + TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())), + false, + false, + ); + diag + } + } + } + + OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + found_trait_ref, + expected_trait_ref, + terr: terr @ TypeError::CyclicTy(_), + }) => self.report_type_parameter_mismatch_cyclic_type_error( + &obligation, + found_trait_ref, + expected_trait_ref, + terr, + ), + OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + found_trait_ref, + expected_trait_ref, + terr: _, + }) => { + match self.report_type_parameter_mismatch_error( + &obligation, + span, + found_trait_ref, + expected_trait_ref, + ) { + Some(err) => err, + None => return, + } + } + + 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) + } + + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { + bug!( + "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" + ) + } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { + match self.report_not_const_evaluatable_error(&obligation, span) { + Some(err) => err, + None => return, + } + } + + // Already reported in the query. + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | + // Already reported. + Overflow(OverflowError::Error(_)) => return, + + Overflow(_) => { + bug!("overflow should be handled before the `report_selection_error` path"); + } + SelectionError::ErrorReporting => { + bug!("ErrorReporting Overflow should not reach `report_selection_err` call") + } + }; + + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + err.emit(); + } + + fn report_const_param_not_wf( + &self, + ty: Ty<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let span = obligation.cause.span; + + let mut diag = match ty.kind() { + _ if ty.has_param() => { + span_bug!(span, "const param tys cannot mention other generic parameters"); + } + ty::Float(_) => { + struct_span_err!( + self.tcx.sess, + span, + E0741, + "`{ty}` is forbidden as the type of a const generic parameter", + ) + } + ty::FnPtr(_) => { + struct_span_err!( + self.tcx.sess, + span, + E0741, + "using function pointers as const generic parameters is forbidden", + ) + } + ty::RawPtr(_) => { + struct_span_err!( + self.tcx.sess, + span, + E0741, + "using raw pointers as const generic parameters is forbidden", + ) + } + ty::Adt(def, _) => { + // We should probably see if we're *allowed* to derive `ConstParamTy` on the type... + let mut diag = struct_span_err!( + self.tcx.sess, + span, + E0741, + "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter", + ); + // Only suggest derive if this isn't a derived obligation, + // and the struct is local. + if let Some(span) = self.tcx.hir().span_if_local(def.did()) + && obligation.cause.code().parent().is_none() + { + if ty.is_structural_eq_shallow(self.tcx) { + diag.span_suggestion( + span, + "add `#[derive(ConstParamTy)]` to the struct", + "#[derive(ConstParamTy)]\n", + Applicability::MachineApplicable, + ); + } else { + // FIXME(adt_const_params): We should check there's not already an + // overlapping `Eq`/`PartialEq` impl. + diag.span_suggestion( + span, + "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct", + "#[derive(ConstParamTy, PartialEq, Eq)]\n", + Applicability::MachineApplicable, + ); + } + } + diag + } + _ => { + struct_span_err!( + self.tcx.sess, + span, + E0741, + "`{ty}` can't be used as a const parameter type", + ) + } + }; + + let mut code = obligation.cause.code(); + let mut pred = obligation.predicate.to_opt_poly_trait_pred(); + while let Some((next_code, next_pred)) = code.parent() { + if let Some(pred) = pred { + let pred = self.instantiate_binder_with_placeholders(pred); + diag.note(format!( + "`{}` must implement `{}`, but it does not", + pred.self_ty(), + pred.print_modifiers_and_trait_path() + )); + } + code = next_code; + pred = next_pred; + } + + diag + } +} + +pub(super) trait InferCtxtPrivExt<'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; + + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>); + + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ); + + fn maybe_detailed_projection_msg( + &self, + pred: ty::ProjectionPredicate<'tcx>, + normalized_ty: ty::Term<'tcx>, + expected_ty: ty::Term<'tcx>, + ) -> Option; + + fn fuzzy_match_tys( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + ignoring_lifetimes: bool, + ) -> Option; + + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>; + + fn find_similar_impl_candidates( + &self, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> Vec>; + + fn report_similar_impl_candidates( + &self, + impl_candidates: &[ImplCandidate<'tcx>], + trait_ref: ty::PolyTraitRef<'tcx>, + body_def_id: LocalDefId, + err: &mut Diagnostic, + other: bool, + param_env: ty::ParamEnv<'tcx>, + ) -> bool; + + fn report_similar_impl_candidates_for_root_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + body_def_id: LocalDefId, + err: &mut Diagnostic, + ); + + /// Gets the parent trait chain start + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)>; + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about + /// a probable version mismatch is added to `err` + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool; + + /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the + /// `trait_ref`. + /// + /// For this to work, `new_self_ty` must have no escaping bound variables. + fn mk_trait_obligation_with_new_self_ty( + &self, + param_env: ty::ParamEnv<'tcx>, + trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, + ) -> PredicateObligation<'tcx>; + + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>); + + fn predicate_can_apply( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool; + + fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); + + fn suggest_unsized_bound_if_applicable( + &self, + err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, + ); + + fn annotate_source_of_ambiguity( + &self, + err: &mut Diagnostic, + impls: &[ambiguity::Ambiguity], + predicate: ty::Predicate<'tcx>, + ); + + fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>); + + fn maybe_indirection_for_unsized( + &self, + err: &mut Diagnostic, + item: &'tcx Item<'tcx>, + param: &'tcx GenericParam<'tcx>, + ) -> bool; + + fn is_recursive_obligation( + &self, + obligated_types: &mut Vec>, + cause_code: &ObligationCauseCode<'tcx>, + ) -> bool; + + fn get_standard_error_message( + &self, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + message: Option, + predicate_is_const: bool, + append_const_msg: Option, + post_message: String, + ) -> String; + + fn get_safe_transmute_error_and_reason( + &self, + obligation: PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + ) -> GetSafeTransmuteErrorAndReason; + + fn add_tuple_trait_message( + &self, + obligation_cause_code: &ObligationCauseCode<'tcx>, + err: &mut Diagnostic, + ); + + fn try_to_add_help_message( + &self, + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + err: &mut Diagnostic, + span: Span, + is_fn_trait: bool, + suggested: bool, + unsatisfied_const: bool, + ); + + fn add_help_message_for_fn_trait( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + err: &mut Diagnostic, + implemented_kind: ty::ClosureKind, + params: ty::Binder<'tcx, Ty<'tcx>>, + ); + + fn maybe_add_note_for_unsatisfied_const( + &self, + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + err: &mut Diagnostic, + span: Span, + ) -> UnsatisfiedConst; + + fn report_closure_error( + &self, + obligation: &PredicateObligation<'tcx>, + closure_def_id: DefId, + found_kind: ty::ClosureKind, + kind: ty::ClosureKind, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + + fn report_type_parameter_mismatch_cyclic_type_error( + &self, + obligation: &PredicateObligation<'tcx>, + found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'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>, + span: Span, + found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ) -> Option>; + + fn report_not_const_evaluatable_error( + &self, + obligation: &PredicateObligation<'tcx>, + span: Span, + ) -> Option>; +} + +impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { + if cond == error { + return true; + } + + // FIXME: It should be possible to deal with `ForAll` in a cleaner way. + let bound_error = error.kind(); + let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { + ( + ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), + ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), + ) => (cond, bound_error.rebind(error)), + _ => { + // FIXME: make this work in other cases too. + return false; + } + }; + + for pred in elaborate(self.tcx, std::iter::once(cond)) { + let bound_predicate = pred.kind(); + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = + bound_predicate.skip_binder() + { + let error = error.to_poly_trait_ref(); + let implication = bound_predicate.rebind(implication.trait_ref); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(); + if self.can_sub(param_env, error, implication) { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); + return true; + } + } + } + + false + } + + #[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( + error.obligation.clone(), + &error.root_obligation, + selection_error, + ); + } + FulfillmentErrorCode::CodeProjectionError(ref e) => { + self.report_projection_error(&error.obligation, e); + } + FulfillmentErrorCode::CodeAmbiguity { overflow: false } => { + self.maybe_report_ambiguity(&error.obligation); + } + FulfillmentErrorCode::CodeAmbiguity { overflow: true } => { + self.report_overflow_no_abort(error.obligation.clone()); + } + FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { + self.report_mismatched_types( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + *err, + ) + .emit(); + } + FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { + let mut diag = self.report_mismatched_consts( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + *err, + ); + let code = error.obligation.cause.code().peel_derives().peel_match_impls(); + if let ObligationCauseCode::BindingObligation(..) + | ObligationCauseCode::ItemObligation(..) + | ObligationCauseCode::ExprBindingObligation(..) + | ObligationCauseCode::ExprItemObligation(..) = code + { + self.note_obligation_cause_code( + error.obligation.cause.body_id, + &mut diag, + error.obligation.predicate, + error.obligation.param_env, + code, + &mut vec![], + &mut Default::default(), + ); + } + diag.emit(); + } + FulfillmentErrorCode::CodeCycle(ref cycle) => { + self.report_overflow_obligation_cycle(cycle); + } + } + } + + #[instrument(level = "debug", skip_all)] + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ) { + let predicate = self.resolve_vars_if_possible(obligation.predicate); + + if predicate.references_error() { + return; + } + + self.probe(|_| { + let ocx = ObligationCtxt::new(self); + + // try to find the mismatched types to report the error with. + // + // this can fail if the problem was higher-ranked, in which + // cause I have no idea for a good error message. + let bound_predicate = predicate.kind(); + let (values, err) = if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) = + bound_predicate.skip_binder() + { + let data = self.instantiate_binder_with_fresh_vars( + obligation.cause.span, + infer::LateBoundRegionConversionTime::HigherRankedType, + bound_predicate.rebind(data), + ); + let unnormalized_term = match data.term.unpack() { + ty::TermKind::Ty(_) => Ty::new_projection( + self.tcx, + data.projection_ty.def_id, + data.projection_ty.args, + ) + .into(), + ty::TermKind::Const(ct) => ty::Const::new_unevaluated( + self.tcx, + ty::UnevaluatedConst { + def: data.projection_ty.def_id, + args: data.projection_ty.args, + }, + ct.ty(), + ) + .into(), + }; + // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice + // to deeply normalize this type. + let normalized_term = + ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term); + + debug!(?obligation.cause, ?obligation.param_env); + + debug!(?normalized_term, data.ty = ?data.term); + + let is_normalized_term_expected = !matches!( + obligation.cause.code().peel_derives(), + ObligationCauseCode::ItemObligation(_) + | ObligationCauseCode::BindingObligation(_, _) + | ObligationCauseCode::ExprItemObligation(..) + | ObligationCauseCode::ExprBindingObligation(..) + | ObligationCauseCode::Coercion { .. } + | ObligationCauseCode::OpaqueType + ); + + // constrain inference variables a bit more to nested obligations from normalize so + // we can have more helpful errors. + // + // we intentionally drop errors from normalization here, + // since the normalization is just done to improve the error message. + let _ = ocx.select_where_possible(); + + if let Err(new_err) = ocx.eq_exp( + &obligation.cause, + obligation.param_env, + is_normalized_term_expected, + normalized_term, + data.term, + ) { + (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err) + } else { + (None, error.err) + } + } else { + (None, error.err) + }; + + let msg = values + .and_then(|(predicate, _, normalized_term, expected_term)| { + self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term) + }) + .unwrap_or_else(|| { + with_forced_trimmed_paths!(format!( + "type mismatch resolving `{}`", + self.resolve_vars_if_possible(predicate) + .print(FmtPrinter::new_with_limit( + self.tcx, + Namespace::TypeNS, + rustc_session::Limit(10), + )) + .unwrap() + .into_buffer() + )) + }); + let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); + + let secondary_span = (|| { + let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = + predicate.kind().skip_binder() + else { + return None; + }; + + let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?; + let trait_assoc_ident = trait_assoc_item.ident(self.tcx); + + let mut associated_items = vec![]; + self.tcx.for_each_relevant_impl( + self.tcx.trait_of_item(proj.projection_ty.def_id)?, + proj.projection_ty.self_ty(), + |impl_def_id| { + associated_items.extend( + self.tcx + .associated_items(impl_def_id) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident), + ); + }, + ); + + let [associated_item]: &[ty::AssocItem] = &associated_items[..] else { + return None; + }; + match self.tcx.hir().get_if_local(associated_item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Type(ty), + .. + }), + ) => Some(( + ty.span, + with_forced_trimmed_paths!(Cow::from(format!( + "type mismatch resolving `{}`", + self.resolve_vars_if_possible(predicate) + .print(FmtPrinter::new_with_limit( + self.tcx, + Namespace::TypeNS, + rustc_session::Limit(5), + )) + .unwrap() + .into_buffer() + ))), + )), + _ => None, + } + })(); + + self.note_type_err( + &mut diag, + &obligation.cause, + secondary_span, + values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| { + infer::ValuePairs::Terms(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + expected_ty, + )) + }), + err, + true, + false, + ); + self.note_obligation_cause(&mut diag, obligation); + diag.emit(); + }); + } + + fn maybe_detailed_projection_msg( + &self, + pred: ty::ProjectionPredicate<'tcx>, + normalized_ty: ty::Term<'tcx>, + expected_ty: ty::Term<'tcx>, + ) -> Option { + let trait_def_id = pred.projection_ty.trait_def_id(self.tcx); + let self_ty = pred.projection_ty.self_ty(); + + with_forced_trimmed_paths! { + if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() { + let fn_kind = self_ty.prefix_string(self.tcx); + let item = match self_ty.kind() { + ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(), + _ => self_ty.to_string(), + }; + Some(format!( + "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \ + returns `{normalized_ty}`", + )) + } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() { + Some(format!( + "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \ + resolves to `{normalized_ty}`" + )) + } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) { + Some(format!( + "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \ + yields `{normalized_ty}`" + )) + } else { + None + } + } + } + + fn fuzzy_match_tys( + &self, + mut a: Ty<'tcx>, + mut b: Ty<'tcx>, + ignoring_lifetimes: bool, + ) -> Option { + /// returns the fuzzy category of a given type, or None + /// if the type can be equated to any type. + fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option { + match t.kind() { + ty::Bool => Some(0), + ty::Char => Some(1), + ty::Str => Some(2), + ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2), + ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4), + ty::Ref(..) | ty::RawPtr(..) => Some(5), + ty::Array(..) | ty::Slice(..) => Some(6), + ty::FnDef(..) | ty::FnPtr(..) => Some(7), + ty::Dynamic(..) => Some(8), + ty::Closure(..) => Some(9), + ty::Tuple(..) => Some(10), + ty::Param(..) => Some(11), + ty::Alias(ty::Projection, ..) => Some(12), + ty::Alias(ty::Inherent, ..) => Some(13), + ty::Alias(ty::Opaque, ..) => Some(14), + ty::Alias(ty::Weak, ..) => Some(15), + ty::Never => Some(16), + ty::Adt(..) => Some(17), + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, + } + } + + let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> { + loop { + match t.kind() { + ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => { + t = *inner + } + _ => break t, + } + } + }; + + if !ignoring_lifetimes { + a = strip_references(a); + b = strip_references(b); + } + + let cat_a = type_category(self.tcx, a)?; + let cat_b = type_category(self.tcx, b)?; + if a == b { + Some(CandidateSimilarity::Exact { ignoring_lifetimes }) + } else if cat_a == cat_b { + match (a.kind(), b.kind()) { + (ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b, + (ty::Foreign(def_a), ty::Foreign(def_b)) => def_a == def_b, + // Matching on references results in a lot of unhelpful + // suggestions, so let's just not do that for now. + // + // We still upgrade successful matches to `ignoring_lifetimes: true` + // to prioritize that impl. + (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => { + self.fuzzy_match_tys(a, b, true).is_some() + } + _ => true, + } + .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes }) + } else if ignoring_lifetimes { + None + } else { + self.fuzzy_match_tys(a, b, true) + } + } + + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { + self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { + hir::GeneratorKind::Gen => "a generator", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", + }) + } + + fn find_similar_impl_candidates( + &self, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> Vec> { + let mut candidates: Vec<_> = self + .tcx + .all_impls(trait_pred.def_id()) + .filter_map(|def_id| { + if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative + || !self.tcx.is_user_visible_dep(def_id.krate) + { + return None; + } + + let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder(); + + self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( + |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, + ) + }) + .collect(); + if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) { + // If any of the candidates is a perfect match, we don't want to show all of them. + // This is particularly relevant for the case of numeric types (as they all have the + // same category). + candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })); + } + candidates + } + + fn report_similar_impl_candidates( + &self, + impl_candidates: &[ImplCandidate<'tcx>], + trait_ref: ty::PolyTraitRef<'tcx>, + body_def_id: LocalDefId, + err: &mut Diagnostic, + other: bool, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + // If we have a single implementation, try to unify it with the trait ref + // that failed. This should uncover a better hint for what *is* implemented. + if let [single] = &impl_candidates { + if self.probe(|_| { + let ocx = ObligationCtxt::new(self); + let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref); + let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), + ); + + ocx.register_obligations( + self.tcx + .predicates_of(single.impl_def_id) + .instantiate(self.tcx, impl_args) + .into_iter() + .map(|(clause, _)| { + Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause) + }), + ); + if !ocx.select_where_possible().is_empty() { + return false; + } + + let mut terrs = vec![]; + for (obligation_arg, impl_arg) in + std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) + { + if let Err(terr) = + ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) + { + terrs.push(terr); + } + if !ocx.select_where_possible().is_empty() { + return false; + } + } + + // Literally nothing unified, just give up. + if terrs.len() == impl_trait_ref.args.len() { + return false; + } + + let cand = + self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| ty, + lt_op: |lt| lt, + ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), + }); + err.highlighted_help(vec![ + (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle), + ("is".to_string(), Style::Highlight), + (" implemented for `".to_string(), Style::NoStyle), + (cand.self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + + if let [TypeError::Sorts(exp_found)] = &terrs[..] { + let exp_found = self.resolve_vars_if_possible(*exp_found); + err.help(format!( + "for that trait implementation, expected `{}`, found `{}`", + exp_found.expected, exp_found.found + )); + } + + true + }) { + return true; + } + } + + let other = if other { "other " } else { "" }; + let report = |candidates: Vec>, err: &mut Diagnostic| { + if candidates.is_empty() { + return false; + } + if let &[cand] = &candidates[..] { + let (desc, mention_castable) = + match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { + (ty::FnPtr(_), ty::FnDef(..)) => { + (" implemented for fn pointer `", ", cast using `as`") + } + (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""), + _ => (" implemented for `", ""), + }; + err.highlighted_help(vec![ + (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle), + ("is".to_string(), Style::Highlight), + (desc.to_string(), Style::NoStyle), + (cand.self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + (mention_castable.to_string(), Style::NoStyle), + ]); + return true; + } + let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id); + // Check if the trait is the same in all cases. If so, we'll only show the type. + let mut traits: Vec<_> = + 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 args[1..] is the same. + let all_traits_equal = traits.len() == 1; + + let candidates: Vec = candidates + .into_iter() + .map(|c| { + if all_traits_equal { + format!("\n {}", c.self_ty()) + } else { + format!("\n {c}") + } + }) + .collect(); + + 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 candidates.len() > 9 { + format!("\nand {} others", candidates.len() - 8) + } else { + String::new() + } + )); + true + }; + + let def_id = trait_ref.def_id(); + if impl_candidates.is_empty() { + if self.tcx.trait_is_auto(def_id) + || self.tcx.lang_items().iter().any(|(_, id)| id == def_id) + || self.tcx.get_diagnostic_name(def_id).is_some() + { + // Mentioning implementers of `Copy`, `Debug` and friends is not useful. + return false; + } + let mut impl_candidates: Vec<_> = self + .tcx + .all_impls(def_id) + // Ignore automatically derived impls and `!Trait` impls. + .filter(|&def_id| { + self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative + || self.tcx.is_automatically_derived(def_id) + }) + .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) + .map(ty::EarlyBinder::instantiate_identity) + .filter(|trait_ref| { + let self_ty = trait_ref.self_ty(); + // Avoid mentioning type parameters. + if let ty::Param(_) = self_ty.kind() { + false + } + // Avoid mentioning types that are private to another crate + else if let ty::Adt(def, _) = self_ty.peel_refs().kind() { + // FIXME(compiler-errors): This could be generalized, both to + // be more granular, and probably look past other `#[fundamental]` + // types, too. + self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx) + } else { + true + } + }) + .collect(); + + impl_candidates.sort(); + impl_candidates.dedup(); + return report(impl_candidates, err); + } + + // Sort impl candidates so that ordering is consistent for UI tests. + // because the ordering of `impl_candidates` may not be deterministic: + // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 + // + // Prefer more similar candidates first, then sort lexicographically + // by their normalized string representation. + let mut impl_candidates: Vec<_> = impl_candidates + .iter() + .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.normalize(self.tcx, ty::ParamEnv::empty()), + }); + cand + }) + .collect(); + impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref)); + let mut impl_candidates: Vec<_> = + impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(); + impl_candidates.dedup(); + + report(impl_candidates, err) + } + + fn report_similar_impl_candidates_for_root_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + body_def_id: LocalDefId, + err: &mut Diagnostic, + ) { + // This is *almost* equivalent to + // `obligation.cause.code().peel_derives()`, but it gives us the + // trait predicate for that corresponding root obligation. This + // lets us get a derived obligation from a type parameter, like + // when calling `string.strip_suffix(p)` where `p` is *not* an + // implementer of `Pattern<'_>`. + let mut code = obligation.cause.code(); + let mut trait_pred = trait_predicate; + let mut peeled = false; + while let Some((parent_code, parent_trait_pred)) = code.parent() { + code = parent_code; + if let Some(parent_trait_pred) = parent_trait_pred { + trait_pred = parent_trait_pred; + peeled = true; + } + } + let def_id = trait_pred.def_id(); + // Mention *all* the `impl`s for the *top most* obligation, the + // user might have meant to use one of them, if any found. We skip + // auto-traits or fundamental traits that might not be exactly what + // the user might expect to be presented with. Instead this is + // useful for less general traits. + if peeled + && !self.tcx.trait_is_auto(def_id) + && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id) + { + let trait_ref = trait_pred.to_poly_trait_ref(); + let impl_candidates = self.find_similar_impl_candidates(trait_pred); + self.report_similar_impl_candidates( + &impl_candidates, + trait_ref, + body_def_id, + err, + true, + obligation.param_env, + ); + } + } + + /// Gets the parent trait chain start + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)> { + match code { + ObligationCauseCode::BuiltinDerivedObligation(data) => { + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + match self.get_parent_trait_ref(&data.parent_code) { + Some(t) => Some(t), + None => { + let ty = parent_trait_ref.skip_binder().self_ty(); + let span = TyCategory::from_ty(self.tcx, ty) + .map(|(_, def_id)| self.tcx.def_span(def_id)); + Some((ty.to_string(), span)) + } + } + } + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { + self.get_parent_trait_ref(&parent_code) + } + _ => None, + } + } + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about + /// a probable version mismatch is added to `err` + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool { + let get_trait_impls = |trait_def_id| { + let mut trait_impls = vec![]; + self.tcx.for_each_relevant_impl( + trait_def_id, + trait_ref.skip_binder().self_ty(), + |impl_def_id| { + trait_impls.push(impl_def_id); + }, + ); + trait_impls + }; + + let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); + let traits_with_same_path: std::collections::BTreeSet<_> = self + .tcx + .all_traits() + .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) + .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) + .collect(); + let mut suggested = false; + for trait_with_same_path in traits_with_same_path { + let trait_impls = get_trait_impls(trait_with_same_path); + if trait_impls.is_empty() { + continue; + } + let impl_spans: Vec<_> = + trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect(); + err.span_help( + impl_spans, + format!("trait impl{} with same name found", pluralize!(trait_impls.len())), + ); + let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); + let crate_msg = + format!("perhaps two different versions of crate `{trait_crate}` are being used?"); + err.note(crate_msg); + suggested = true; + } + suggested + } + + fn mk_trait_obligation_with_new_self_ty( + &self, + param_env: ty::ParamEnv<'tcx>, + trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, + ) -> PredicateObligation<'tcx> { + let trait_pred = + trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty)); + + Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred) + } + + #[instrument(skip(self), level = "debug")] + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + // Unable to successfully determine, probably means + // insufficient type information, but could mean + // ambiguous impls. The latter *ought* to be a + // coherence violation, so we don't report it here. + + let predicate = self.resolve_vars_if_possible(obligation.predicate); + let span = obligation.cause.span; + + debug!(?predicate, obligation.cause.code = ?obligation.cause.code()); + + // Ambiguity errors are often caused as fallout from earlier errors. + // We ignore them if this `infcx` is tainted in some cases below. + + let bound_predicate = predicate.kind(); + let mut err = match bound_predicate.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + let trait_ref = bound_predicate.rebind(data.trait_ref); + debug!(?trait_ref); + + if predicate.references_error() { + return; + } + + // This is kind of a hack: it frequently happens that some earlier + // error prevents types from being fully inferred, and then we get + // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we + // could just skip over all checks where the self-ty is an + // inference variable, but I was afraid that there might be an + // inference variable created, registered as an obligation, and + // then never forced by writeback, and hence by skipping here we'd + // be ignoring the fact that we don't KNOW the type works + // out. Though even that would probably be harmless, given that + // we're only talking about builtin traits, which are known to be + // inhabited. We used to check for `self.tcx.sess.has_errors()` to + // avoid inundating the user with unnecessary errors, but we now + // check upstream for type errors and don't add the obligations to + // begin with in those cases. + if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { + if let None = self.tainted_by_errors() { + self.emit_inference_failure_err( + obligation.cause.body_id, + span, + trait_ref.self_ty().skip_binder().into(), + ErrorCode::E0282, + false, + ) + .emit(); + } + return; + } + + // Typically, this ambiguity should only happen if + // there are unresolved type inference variables + // (otherwise it would suggest a coherence + // failure). But given #21974 that is not necessarily + // the case -- we can have multiple where clauses that + // are only distinguished by a region, which results + // in an ambiguity even when all types are fully + // known, since we don't dispatch based on region + // relationships. + + // Pick the first substitution that still contains inference variables as the one + // we're going to emit an error for. If there are none (see above), fall back to + // a more general error. + let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer()); + + let mut err = if let Some(subst) = subst { + self.emit_inference_failure_err( + obligation.cause.body_id, + span, + subst, + ErrorCode::E0283, + true, + ) + } else { + struct_span_err!( + self.tcx.sess, + span, + E0283, + "type annotations needed: cannot satisfy `{}`", + predicate, + ) + }; + + let mut ambiguities = ambiguity::recompute_applicable_impls( + self.infcx, + &obligation.with(self.tcx, trait_ref), + ); + let has_non_region_infer = + trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer()); + // It doesn't make sense to talk about applicable impls if there are more than a + // handful of them. If there are a lot of them, but only a few of them have no type + // params, we only show those, as they are more likely to be useful/intended. + if ambiguities.len() > 5 { + let infcx = self.infcx; + if !ambiguities.iter().all(|option| match option { + DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(), + ParamEnv(_) => true, + }) { + // If not all are blanket impls, we filter blanked impls out. + ambiguities.retain(|option| match option { + DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(), + ParamEnv(_) => true, + }); + } + } + if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { + if self.tainted_by_errors().is_some() && subst.is_none() { + // If `subst.is_none()`, then this is probably two param-env + // candidates or impl candidates that are equal modulo lifetimes. + // Therefore, if we've already emitted an error, just skip this + // one, since it's not particularly actionable. + err.cancel(); + return; + } + self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate); + } else { + if self.tainted_by_errors().is_some() { + err.cancel(); + return; + } + err.note(format!("cannot satisfy `{predicate}`")); + let impl_candidates = self + .find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap()); + if impl_candidates.len() < 40 { + self.report_similar_impl_candidates( + impl_candidates.as_slice(), + trait_ref, + obligation.cause.body_id, + &mut err, + false, + obligation.param_env, + ); + } + } + + if let ObligationCauseCode::ItemObligation(def_id) + | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() + { + self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); + } + + if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack()) + && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) + { + let mut expr_finder = FindExprBySpan::new(span); + expr_finder.visit_expr(&self.tcx.hir().body(body_id).value); + + if let Some(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. } + ) = expr_finder.result + && let [ + .., + trait_path_segment @ hir::PathSegment { + res: Res::Def(DefKind::Trait, trait_id), + .. + }, + hir::PathSegment { + ident: assoc_item_name, + res: Res::Def(_, item_id), + .. + } + ] = path.segments + && data.trait_ref.def_id == *trait_id + && self.tcx.trait_of_item(*item_id) == Some(*trait_id) + && let None = self.tainted_by_errors() + { + let (verb, noun) = match self.tcx.associated_item(item_id).kind { + ty::AssocKind::Const => ("refer to the", "constant"), + ty::AssocKind::Fn => ("call", "function"), + // This is already covered by E0223, but this following single match + // arm doesn't hurt here. + ty::AssocKind::Type => ("refer to the", "type"), + }; + + // Replace the more general E0283 with a more specific error + err.cancel(); + err = self.tcx.sess.struct_span_err_with_code( + span, + format!( + "cannot {verb} associated {noun} on trait without specifying the \ + corresponding `impl` type", + ), + rustc_errors::error_code!(E0790), + ); + + if let Some(local_def_id) = data.trait_ref.def_id.as_local() + && let Some(hir::Node::Item(hir::Item { + ident: trait_name, + kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), + .. + })) = self.tcx.hir().find_by_def_id(local_def_id) + && let Some(method_ref) = trait_item_refs + .iter() + .find(|item_ref| item_ref.ident == *assoc_item_name) + { + err.span_label( + method_ref.span, + format!("`{trait_name}::{assoc_item_name}` defined here"), + ); + } + + err.span_label(span, format!("cannot {verb} associated {noun} of trait")); + + let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id); + + if let Some(impl_def_id) = + trait_impls.non_blanket_impls().values().flatten().next() + { + let non_blanket_impl_count = + trait_impls.non_blanket_impls().values().flatten().count(); + // If there is only one implementation of the trait, suggest using it. + // Otherwise, use a placeholder comment for the implementation. + let (message, self_type) = if non_blanket_impl_count == 1 { + ( + "use the fully-qualified path to the only available \ + implementation", + format!( + "{}", + self.tcx.type_of(impl_def_id).instantiate_identity() + ), + ) + } else { + ( + "use a fully-qualified path to a specific available \ + implementation", + "/* self type */".to_string(), + ) + }; + let mut suggestions = vec![( + path.span.shrink_to_lo(), + format!("<{self_type} as "), + )]; + if let Some(generic_arg) = trait_path_segment.args { + let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext); + // get rid of :: between Trait and + // must be '::' between them, otherwise the parser won't accept the code + suggestions.push((between_span, "".to_string(),)); + suggestions.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string())); + } else { + suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), ">".to_string())); + } + err.multipart_suggestion( + message, + suggestions, + Applicability::MaybeIncorrect + ); + } + } + }; + + err + } + + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + // Same hacky approach as above to avoid deluging user + // with error messages. + if arg.references_error() + || self.tcx.sess.has_errors().is_some() + || self.tainted_by_errors().is_some() + { + return; + } + + self.emit_inference_failure_err( + obligation.cause.body_id, + span, + arg, + ErrorCode::E0282, + false, + ) + } + + ty::PredicateKind::Subtype(data) => { + if data.references_error() + || self.tcx.sess.has_errors().is_some() + || self.tainted_by_errors().is_some() + { + // no need to overload user in such cases + return; + } + let SubtypePredicate { a_is_expected: _, a, b } = data; + // both must be type variables, or the other would've been instantiated + assert!(a.is_ty_var() && b.is_ty_var()); + self.emit_inference_failure_err( + obligation.cause.body_id, + span, + a.into(), + ErrorCode::E0282, + true, + ) + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { + if predicate.references_error() || self.tainted_by_errors().is_some() { + return; + } + let subst = data + .projection_ty + .args + .iter() + .chain(Some(data.term.into_arg())) + .find(|g| g.has_non_region_infer()); + if let Some(subst) = subst { + let mut err = self.emit_inference_failure_err( + obligation.cause.body_id, + span, + subst, + ErrorCode::E0284, + true, + ); + err.note(format!("cannot satisfy `{predicate}`")); + err + } else { + // If we can't find a substitution, just print a generic error + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot satisfy `{}`", + predicate, + ); + err.span_label(span, format!("cannot satisfy `{predicate}`")); + err + } + } + + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { + if predicate.references_error() || self.tainted_by_errors().is_some() { + return; + } + let subst = data.walk().find(|g| g.is_non_region_infer()); + if let Some(subst) = subst { + let err = self.emit_inference_failure_err( + obligation.cause.body_id, + span, + subst, + ErrorCode::E0284, + true, + ); + err + } else { + // If we can't find a substitution, just print a generic error + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot satisfy `{}`", + predicate, + ); + err.span_label(span, format!("cannot satisfy `{predicate}`")); + err + } + } + _ => { + if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() { + return; + } + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot satisfy `{}`", + predicate, + ); + err.span_label(span, format!("cannot satisfy `{predicate}`")); + err + } + }; + self.note_obligation_cause(&mut err, obligation); + err.emit(); + } + + fn annotate_source_of_ambiguity( + &self, + err: &mut Diagnostic, + ambiguities: &[ambiguity::Ambiguity], + predicate: ty::Predicate<'tcx>, + ) { + let mut spans = vec![]; + let mut crates = vec![]; + let mut post = vec![]; + let mut has_param_env = false; + for ambiguity in ambiguities { + match ambiguity { + ambiguity::Ambiguity::DefId(impl_def_id) => { + match self.tcx.span_of_impl(*impl_def_id) { + Ok(span) => spans.push(span), + Err(name) => { + crates.push(name); + if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) { + post.push(header); + } + } + } + } + ambiguity::Ambiguity::ParamEnv(span) => { + has_param_env = true; + spans.push(*span); + } + } + } + let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect(); + crate_names.sort(); + crate_names.dedup(); + post.sort(); + post.dedup(); + + if self.tainted_by_errors().is_some() + && (crate_names.len() == 1 + && spans.len() == 0 + && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) + || predicate.visit_with(&mut HasNumericInferVisitor).is_break()) + { + // Avoid complaining about other inference issues for expressions like + // `42 >> 1`, where the types are still `{integer}`, but we want to + // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too? + // NOTE(eddyb) this was `.cancel()`, but `err` + // is borrowed, so we can't fully defuse it. + err.downgrade_to_delayed_bug(); + return; + } + + let msg = format!( + "multiple `impl`s{} satisfying `{}` found", + if has_param_env { " or `where` clauses" } else { "" }, + predicate + ); + let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { + format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::>().join("\n"),) + } else if post.len() == 1 { + format!(": `{}`", post[0]) + } else { + String::new() + }; + + match (spans.len(), crates.len(), crate_names.len()) { + (0, 0, 0) => { + err.note(format!("cannot satisfy `{predicate}`")); + } + (0, _, 1) => { + err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,)); + } + (0, _, _) => { + err.note(format!( + "{} in the following crates: {}{}", + msg, + crate_names.join(", "), + post, + )); + } + (_, 0, 0) => { + let span: MultiSpan = spans.into(); + err.span_note(span, msg); + } + (_, 1, 1) => { + let span: MultiSpan = spans.into(); + err.span_note(span, msg); + err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,)); + } + _ => { + let span: MultiSpan = spans.into(); + err.span_note(span, msg); + err.note(format!( + "and more `impl`s found in the following crates: {}{}", + crate_names.join(", "), + post, + )); + } + } + } + + /// Returns `true` if the trait predicate may apply for *some* assignment + /// to the type parameters. + fn predicate_can_apply( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + struct ParamToVarFolder<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, + var_map: FxHashMap, Ty<'tcx>>, + } + + impl<'a, 'tcx> TypeFolder> for ParamToVarFolder<'a, 'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + 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::MiscVariable, + span: DUMMY_SP, + }) + }) + } else { + ty.super_fold_with(self) + } + } + } + + self.probe(|_| { + let cleaned_pred = + pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); + + let InferOk { value: cleaned_pred, .. } = + self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred); + + let obligation = + Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred); + + self.predicate_may_hold(&obligation) + }) + } + + fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>) { + // First, attempt to add note to this error with an async-await-specific + // message, and fall back to regular note otherwise. + if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { + self.note_obligation_cause_code( + obligation.cause.body_id, + err, + obligation.predicate, + obligation.param_env, + obligation.cause.code(), + &mut vec![], + &mut Default::default(), + ); + self.suggest_unsized_bound_if_applicable(err, obligation); + } + } + + #[instrument(level = "debug", skip_all)] + fn suggest_unsized_bound_if_applicable( + &self, + err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, + ) { + let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = + obligation.predicate.kind().skip_binder() + else { + return; + }; + let (ObligationCauseCode::BindingObligation(item_def_id, span) + | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) = + *obligation.cause.code().peel_derives() + else { + return; + }; + debug!(?pred, ?item_def_id, ?span); + + let (Some(node), true) = ( + self.tcx.hir().get_if_local(item_def_id), + Some(pred.def_id()) == self.tcx.lang_items().sized_trait(), + ) else { + return; + }; + self.maybe_suggest_unsized_generics(err, span, node); + } + + #[instrument(level = "debug", skip_all)] + fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>) { + let Some(generics) = node.generics() else { + return; + }; + let sized_trait = self.tcx.lang_items().sized_trait(); + debug!(?generics.params); + debug!(?generics.predicates); + let Some(param) = generics.params.iter().find(|param| param.span == span) else { + return; + }; + // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit + // `Sized` bound is there intentionally and we don't need to suggest relaxing it. + let explicitly_sized = generics + .bounds_for_param(param.def_id) + .flat_map(|bp| bp.bounds) + .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait); + if explicitly_sized { + return; + } + debug!(?param); + match node { + hir::Node::Item( + item @ hir::Item { + // Only suggest indirection for uses of type parameters in ADTs. + kind: + hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..), + .. + }, + ) => { + if self.maybe_indirection_for_unsized(err, item, param) { + return; + } + } + _ => {} + }; + // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`. + let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param.def_id) + { + (s, " +") + } else { + (span.shrink_to_hi(), ":") + }; + err.span_suggestion_verbose( + span, + "consider relaxing the implicit `Sized` restriction", + format!("{separator} ?Sized"), + Applicability::MachineApplicable, + ); + } + + fn maybe_indirection_for_unsized( + &self, + err: &mut Diagnostic, + item: &Item<'tcx>, + param: &GenericParam<'tcx>, + ) -> bool { + // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a + // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S(T);` + // is not. Look for invalid "bare" parameter uses, and suggest using indirection. + let mut visitor = + FindTypeParam { param: param.name.ident().name, invalid_spans: vec![], nested: false }; + visitor.visit_item(item); + if visitor.invalid_spans.is_empty() { + return false; + } + let mut multispan: MultiSpan = param.span.into(); + multispan.push_span_label( + param.span, + format!("this could be changed to `{}: ?Sized`...", param.name.ident()), + ); + for sp in visitor.invalid_spans { + multispan.push_span_label( + sp, + format!("...if indirection were used here: `Box<{}>`", param.name.ident()), + ); + } + err.span_help( + multispan, + format!( + "you could relax the implicit `Sized` bound on `{T}` if it were \ + used through indirection like `&{T}` or `Box<{T}>`", + T = param.name.ident(), + ), + ); + true + } + + fn is_recursive_obligation( + &self, + obligated_types: &mut Vec>, + cause_code: &ObligationCauseCode<'tcx>, + ) -> bool { + if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let self_ty = parent_trait_ref.skip_binder().self_ty(); + if obligated_types.iter().any(|ot| ot == &self_ty) { + return true; + } + if let ty::Adt(def, args) = self_ty.kind() + && let [arg] = &args[..] + && let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Adt(inner_def, _) = ty.kind() + && inner_def == def + { + return true; + } + } + false + } + + fn get_standard_error_message( + &self, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + message: Option, + predicate_is_const: bool, + append_const_msg: Option, + post_message: String, + ) -> String { + message + .and_then(|cannot_do_this| { + match (predicate_is_const, append_const_msg) { + // do nothing if predicate is not const + (false, _) => Some(cannot_do_this), + // suggested using default post message + (true, Some(AppendConstMessage::Default)) => { + Some(format!("{cannot_do_this} in const contexts")) + } + // overridden post message + (true, Some(AppendConstMessage::Custom(custom_msg))) => { + Some(format!("{cannot_do_this}{custom_msg}")) + } + // fallback to generic message + (true, None) => None, + } + }) + .unwrap_or_else(|| { + format!("the trait bound `{trait_predicate}` is not satisfied{post_message}") + }) + } + + fn get_safe_transmute_error_and_reason( + &self, + obligation: PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + ) -> GetSafeTransmuteErrorAndReason { + use rustc_transmute::Answer; + + // Erase regions because layout code doesn't particularly care about regions. + let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref)); + + let src_and_dst = rustc_transmute::Types { + dst: trait_ref.args.type_at(0), + src: trait_ref.args.type_at(1), + }; + let scope = trait_ref.args.type_at(2); + let Some(assume) = rustc_transmute::Assume::from_const( + self.infcx.tcx, + obligation.param_env, + trait_ref.args.const_at(3), + ) else { + span_bug!( + span, + "Unable to construct rustc_transmute::Assume where it was previously possible" + ); + }; + + match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable( + obligation.cause, + src_and_dst, + scope, + assume, + ) { + Answer::No(reason) => { + let dst = trait_ref.args.type_at(0); + let src = trait_ref.args.type_at(1); + let err_msg = format!( + "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`" + ); + let safe_transmute_explanation = match reason { + rustc_transmute::Reason::SrcIsUnspecified => { + format!("`{src}` does not have a well-specified layout") + } + + rustc_transmute::Reason::DstIsUnspecified => { + format!("`{dst}` does not have a well-specified layout") + } + + rustc_transmute::Reason::DstIsBitIncompatible => { + format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`") + } + + rustc_transmute::Reason::DstIsPrivate => format!( + "`{dst}` is or contains a type or field that is not visible in that scope" + ), + rustc_transmute::Reason::DstIsTooBig => { + format!("The size of `{src}` is smaller than the size of `{dst}`") + } + rustc_transmute::Reason::SrcSizeOverflow => { + format!( + "values of the type `{src}` are too big for the current architecture" + ) + } + rustc_transmute::Reason::DstSizeOverflow => { + format!( + "values of the type `{dst}` are too big for the current architecture" + ) + } + rustc_transmute::Reason::DstHasStricterAlignment { + src_min_align, + dst_min_align, + } => { + format!( + "The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})" + ) + } + rustc_transmute::Reason::DstIsMoreUnique => { + format!("`{src}` is a shared reference, but `{dst}` is a unique reference") + } + // Already reported by rustc + rustc_transmute::Reason::TypeError => { + return GetSafeTransmuteErrorAndReason::Silent; + } + rustc_transmute::Reason::SrcLayoutUnknown => { + format!("`{src}` has an unknown layout") + } + rustc_transmute::Reason::DstLayoutUnknown => { + format!("`{dst}` has an unknown layout") + } + }; + GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation } + } + // Should never get a Yes at this point! We already ran it before, and did not get a Yes. + Answer::Yes => span_bug!( + span, + "Inconsistent rustc_transmute::is_transmutable(...) result, got Yes", + ), + other => span_bug!(span, "Unsupported rustc_transmute::Answer variant: `{other:?}`"), + } + } + + fn add_tuple_trait_message( + &self, + obligation_cause_code: &ObligationCauseCode<'tcx>, + err: &mut Diagnostic, + ) { + match obligation_cause_code { + ObligationCauseCode::RustCall => { + err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); + } + ObligationCauseCode::BindingObligation(def_id, _) + | ObligationCauseCode::ItemObligation(def_id) + if self.tcx.is_fn_trait(*def_id) => + { + err.code(rustc_errors::error_code!(E0059)); + err.set_primary_message(format!( + "type parameter to bare `{}` trait must be a tuple", + self.tcx.def_path_str(*def_id) + )); + } + _ => {} + } + } + + fn try_to_add_help_message( + &self, + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + trait_predicate: &ty::PolyTraitPredicate<'tcx>, + err: &mut Diagnostic, + span: Span, + is_fn_trait: bool, + suggested: bool, + unsatisfied_const: bool, + ) { + let body_def_id = obligation.cause.body_id; + let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } = + obligation.cause.code() + { + *rhs_span + } else { + span + }; + + // Try to report a help message + if is_fn_trait + && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( + obligation.param_env, + trait_ref.self_ty(), + trait_predicate.skip_binder().polarity, + ) + { + self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); + } else if !trait_ref.has_non_region_infer() + && self.predicate_can_apply(obligation.param_env, *trait_predicate) + { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + self.suggest_restricting_param_bound( + err, + *trait_predicate, + None, + obligation.cause.body_id, + ); + } else if trait_ref.def_id().is_local() + && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() + && !self.tcx.trait_is_auto(trait_ref.def_id()) + && !self.tcx.trait_is_alias(trait_ref.def_id()) + { + err.span_help( + self.tcx.def_span(trait_ref.def_id()), + crate::fluent_generated::trait_selection_trait_has_no_impls, + ); + } else if !suggested && !unsatisfied_const { + // Can't show anything else useful, try to find similar impls. + let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); + if !self.report_similar_impl_candidates( + &impl_candidates, + trait_ref, + body_def_id, + err, + true, + obligation.param_env, + ) { + self.report_similar_impl_candidates_for_root_obligation( + &obligation, + *trait_predicate, + body_def_id, + err, + ); + } + + self.suggest_convert_to_slice( + err, + obligation, + trait_ref, + impl_candidates.as_slice(), + span, + ); + } + } + + fn add_help_message_for_fn_trait( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + err: &mut Diagnostic, + implemented_kind: ty::ClosureKind, + params: ty::Binder<'tcx, Ty<'tcx>>, + ) { + // If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following + // suggestion to add trait bounds for the type, since we only typically implement + // these traits once. + + // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying + // to implement. + let selected_kind = self + .tcx + .fn_trait_kind_from_def_id(trait_ref.def_id()) + .expect("expected to map DefId to ClosureKind"); + if !implemented_kind.extends(selected_kind) { + err.note(format!( + "`{}` implements `{}`, but it must implement `{}`, which is more general", + trait_ref.skip_binder().self_ty(), + implemented_kind, + selected_kind + )); + } + + // Note any argument mismatches + let given_ty = params.skip_binder(); + let expected_ty = trait_ref.skip_binder().args.type_at(1); + if let ty::Tuple(given) = given_ty.kind() + && let ty::Tuple(expected) = expected_ty.kind() + { + if expected.len() != given.len() { + // Note number of types that were expected and given + err.note( + format!( + "expected a closure taking {} argument{}, but one taking {} argument{} was given", + given.len(), + pluralize!(given.len()), + expected.len(), + pluralize!(expected.len()), + ) + ); + } else if !self.same_type_modulo_infer(given_ty, expected_ty) { + // Print type mismatch + let (expected_args, given_args) = + self.cmp(given_ty, expected_ty); + err.note_expected_found( + &"a closure with arguments", + expected_args, + &"a closure with arguments", + given_args, + ); + } + } + } + + fn maybe_add_note_for_unsatisfied_const( + &self, + _obligation: &PredicateObligation<'tcx>, + _trait_ref: ty::PolyTraitRef<'tcx>, + _trait_predicate: &ty::PolyTraitPredicate<'tcx>, + _err: &mut Diagnostic, + _span: Span, + ) -> UnsatisfiedConst { + let unsatisfied_const = UnsatisfiedConst(false); + // FIXME(effects) + unsatisfied_const + } + + fn report_closure_error( + &self, + obligation: &PredicateObligation<'tcx>, + closure_def_id: DefId, + found_kind: ty::ClosureKind, + kind: ty::ClosureKind, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let closure_span = self.tcx.def_span(closure_def_id); + + let mut err = ClosureKindMismatch { + closure_span, + expected: kind, + found: found_kind, + cause_span: obligation.cause.span, + fn_once_label: None, + fn_mut_label: None, + }; + + // Additional context information explaining why the closure only implements + // a particular trait. + if let Some(typeck_results) = &self.typeck_results { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) { + (ty::ClosureKind::FnOnce, Some((span, place))) => { + err.fn_once_label = Some(ClosureFnOnceLabel { + span: *span, + place: ty::place_to_string_for_capture(self.tcx, &place), + }) + } + (ty::ClosureKind::FnMut, Some((span, place))) => { + err.fn_mut_label = Some(ClosureFnMutLabel { + span: *span, + place: ty::place_to_string_for_capture(self.tcx, &place), + }) + } + _ => {} + } + } + + self.tcx.sess.create_err(err) + } + + fn report_type_parameter_mismatch_cyclic_type_error( + &self, + obligation: &PredicateObligation<'tcx>, + found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + terr: TypeError<'tcx>, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let self_ty = found_trait_ref.self_ty().skip_binder(); + let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() { + ( + ObligationCause::dummy_with_span(self.tcx.def_span(def_id)), + TypeError::CyclicTy(self_ty), + ) + } else { + (obligation.cause.clone(), terr) + }; + self.report_and_explain_type_error( + TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref), + terr, + ) + } + + 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(_) => { + "opaque type".to_string() + } + 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>, + span: Span, + found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ) -> Option> { + let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); + let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); + + if expected_trait_ref.self_ty().references_error() { + return None; + } + + let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else { + return None; + }; + + let found_did = match *found_trait_ty.kind() { + ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Generator(did, ..) => { + Some(did) + } + ty::Adt(def, _) => Some(def.did()), + _ => None, + }; + + let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did)); + let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did)); + + if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + // We check closures twice, with obligations flowing in different directions, + // but we want to complain about them only once. + return None; + } + + self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + + let mut not_tupled = false; + + let found = match found_trait_ref.skip_binder().args.type_at(1).kind() { + ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], + _ => { + not_tupled = true; + vec![ArgKind::empty()] + } + }; + + let expected_ty = expected_trait_ref.skip_binder().args.type_at(1); + let expected = match expected_ty.kind() { + ty::Tuple(ref tys) => { + tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect() + } + _ => { + not_tupled = true; + vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())] + } + }; + + // If this is a `Fn` family trait and either the expected or found + // is not tupled, then fall back to just a regular mismatch error. + // This shouldn't be common unless manually implementing one of the + // traits manually, but don't make it more confusing when it does + // happen. + Some( + if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().gen_trait() && not_tupled + { + self.report_and_explain_type_error( + TypeTrace::poly_trait_refs( + &obligation.cause, + true, + expected_trait_ref, + found_trait_ref, + ), + ty::error::TypeError::Mismatch, + ) + } else if found.len() == expected.len() { + self.report_closure_arg_mismatch( + span, + found_span, + found_trait_ref, + expected_trait_ref, + obligation.cause.code(), + found_node, + obligation.param_env, + ) + } else { + let (closure_span, closure_arg_span, found) = found_did + .and_then(|did| { + let node = self.tcx.hir().get_if_local(did)?; + let (found_span, closure_arg_span, found) = + self.get_fn_like_arguments(node)?; + Some((Some(found_span), closure_arg_span, found)) + }) + .unwrap_or((found_span, None, found)); + + self.report_arg_count_mismatch( + span, + closure_span, + expected, + found, + found_trait_ty.is_closure(), + closure_arg_span, + ) + }, + ) + } + + fn report_not_const_evaluatable_error( + &self, + obligation: &PredicateObligation<'tcx>, + span: Span, + ) -> Option> { + if !self.tcx.features().generic_const_exprs { + let mut err = self + .tcx + .sess + .struct_span_err(span, "constant expression depends on a generic parameter"); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + // + // Note that with `feature(generic_const_exprs)` this case should not + // be reachable. + err.note("this may fail depending on what value the parameter takes"); + err.emit(); + return None; + } + + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { + let ty::ConstKind::Unevaluated(uv) = ct.kind() else { + bug!("const evaluatable failed for non-unevaluated const `{ct:?}`"); + }; + let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); + let const_span = self.tcx.def_span(uv.def); + match self.tcx.sess.source_map().span_to_snippet(const_span) { + Ok(snippet) => err.help(format!( + "try adding a `where` bound using this expression: `where [(); {snippet}]:`" + )), + _ => err.help("consider adding a `where` bound using this expression"), + }; + Some(err) + } + _ => { + span_bug!( + span, + "unexpected non-ConstEvaluatable predicate, this should not be reachable" + ) + } + } + } +} diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 956f8e047d705..ab81d77a268d8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -204,7 +204,7 @@ fn do_normalize_predicates<'tcx>( let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) { Ok(predicates) => predicates, Err(errors) => { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(reported); } }; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 93e8e1f4bb1ef..73c2ff3c53661 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1644,7 +1644,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( let env_predicates = data .projection_bounds() .filter(|bound| bound.item_def_id() == obligation.predicate.def_id) - .map(|p| ty::Clause::from_projection_clause(tcx, p.with_self_ty(tcx, object_ty))); + .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx)); assemble_candidates_from_predicates( selcx, @@ -1813,7 +1813,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Tuple(..) // Integers and floats always have `u8` as their discriminant. @@ -1863,7 +1862,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never // Extern types have unit metadata, according to RFC 2850 | ty::Foreign(_) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 9484a50e3a913..86ea7a2bf8392 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -36,7 +36,6 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::FnPtr(_) | ty::Char | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::RawPtr(_) | ty::Ref(..) | ty::Str @@ -218,8 +217,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(_) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) => { + | ty::GeneratorWitness(..) => { // these types never have a destructor } 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 e3da87a221064..bead8758ad604 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -436,8 +436,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Ref(_, _, _) | ty::Closure(_, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(_, _) + | ty::GeneratorWitness(..) | ty::Never | ty::Tuple(_) | ty::Error(_) => return true, @@ -569,8 +568,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Generator(..) | ty::Never | ty::Tuple(_) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) => { + | ty::GeneratorWitness(..) => { // Only consider auto impls if there are no manual impls for the root of `self_ty`. // // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl @@ -946,8 +944,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Closure(..) | ty::Generator(..) | ty::Tuple(_) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) => { + | ty::GeneratorWitness(..) => { // These are built-in, and cannot have a custom `impl const Destruct`. candidates.vec.push(ConstDestructCandidate(None)); } @@ -1020,8 +1017,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::Generator(_, _, _) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Never | ty::Alias(..) | ty::Param(_) @@ -1083,7 +1079,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Tuple(..) | ty::Alias(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index eadac70057cd8..08ee9c73bf8aa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1238,10 +1238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let generator = args.as_generator(); stack.extend([generator.tupled_upvars_ty(), generator.witness()]); } - ty::GeneratorWitness(tys) => { - stack.extend(tcx.erase_late_bound_regions(tys).to_vec()); - } - ty::GeneratorWitnessMIR(def_id, args) => { + ty::GeneratorWitness(def_id, args) => { let tcx = self.tcx(); stack.extend(tcx.generator_hidden_types(def_id).map(|bty| { let ty = bty.instantiate(tcx, args); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 24d3163385051..8871de194a634 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,9 +35,11 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitObligation; -use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::dep_graph::dep_kinds; +use rustc_middle::dep_graph::DepNodeIndex; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::DefiningAnchor; +use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::relate::TypeRelation; @@ -1435,7 +1437,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { OP: FnOnce(&mut Self) -> R, { let (result, dep_node) = - self.tcx().dep_graph.with_anon_task(self.tcx(), DepKind::TraitSelect, || op(self)); + self.tcx().dep_graph.with_anon_task(self.tcx(), dep_kinds::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } @@ -2130,7 +2132,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -2229,22 +2230,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } - ty::GeneratorWitness(binder) => { - let witness_tys = binder.skip_binder(); - for witness_ty in witness_tys.iter() { - let resolved = self.infcx.shallow_resolve(witness_ty); - if resolved.is_ty_var() { - return Ambiguous; - } - } - // (*) binder moved here - let all_vars = self.tcx().mk_bound_variable_kinds_from_iter( - obligation.predicate.bound_vars().iter().chain(binder.bound_vars().iter()), - ); - Where(ty::Binder::bind_with_vars(witness_tys.to_vec(), all_vars)) - } - - ty::GeneratorWitnessMIR(def_id, ref args) => { + ty::GeneratorWitness(def_id, ref args) => { let hidden_types = bind_generator_hidden_types_above( self.infcx, def_id, @@ -2349,12 +2335,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { t.rebind([ty].into_iter().chain(iter::once(witness)).collect()) } - ty::GeneratorWitness(types) => { - debug_assert!(!types.has_escaping_bound_vars()); - types.map_bound(|types| types.to_vec()) - } - - ty::GeneratorWitnessMIR(def_id, ref args) => { + ty::GeneratorWitness(def_id, ref args) => { bind_generator_hidden_types_above(self.infcx, def_id, args, t.bound_vars()) } @@ -2662,7 +2643,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { current: ty::PolyTraitPredicate<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { - let mut matcher = ty::_match::Match::new(self.tcx(), param_env); + let mut matcher = MatchAgainstFreshVars::new(self.tcx(), param_env); matcher.relate(previous, current).is_ok() } @@ -3114,32 +3095,30 @@ fn bind_generator_hidden_types_above<'tcx>( .generator_hidden_types(def_id) // Deduplicate tys to avoid repeated work. .filter(|bty| seen_tys.insert(*bty)) - .map(|bty| { - let mut ty = bty.instantiate(tcx, args); - + .map(|mut bty| { // Only remap erased regions if we use them. if considering_regions { - ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { - ty::ReErased => { - let br = ty::BoundRegion { - var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(None), - }; - counter += 1; - ty::Region::new_late_bound(tcx, current_depth, br) - } - r => bug!("unexpected region: {r:?}"), + bty = bty.map_bound(|ty| { + tcx.fold_regions(ty, |r, current_depth| match r.kind() { + ty::ReErased => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon, + }; + counter += 1; + ty::Region::new_late_bound(tcx, current_depth, br) + } + r => bug!("unexpected region: {r:?}"), + }) }) } - ty + bty.instantiate(tcx, args) }) .collect(); - if considering_regions { - debug_assert!(!hidden_types.has_erased_regions()); - } - let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain( - (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))), - )); + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain( + (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)), + )); ty::Binder::bind_with_vars(hidden_types, bound_vars) } diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 0864e4dc84199..fc9b424369a78 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -79,7 +79,7 @@ impl<'tcx> TypeVisitor> for Search<'tcx> { ty::Closure(..) => { return ControlFlow::Break(ty); } - ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { + ty::Generator(..) | ty::GeneratorWitness(..) => { return ControlFlow::Break(ty); } ty::FnDef(..) => { diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index d3c4dc45923d9..9d6be76890194 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -22,9 +22,14 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { assert!(!ty.is_ty_var(), "should have resolved vars before calling"); if self.infcx.next_trait_solver() { - while let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) = - *ty.kind() - { + // FIXME(-Ztrait-solver=next): correctly handle + // overflow here. + for _ in 0..256 { + let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) = *ty.kind() + else { + break; + }; + let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::NormalizeProjectionType, span: self.cause.span, @@ -49,6 +54,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { break; } } + Ok(ty) } else { Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx)) diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index e41073937be11..f23c100a686c6 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -316,7 +316,7 @@ fn vtable_entries<'tcx>( dump_vtable_entries(tcx, sp, trait_ref, &entries); } - tcx.arena.alloc_from_iter(entries.into_iter()) + tcx.arena.alloc_from_iter(entries) } /// Find slot base for trait methods within vtable entries of another trait diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f26310665f9fa..060df7726138b 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -105,13 +105,13 @@ pub fn unnormalized_obligations<'tcx>( /// Returns the obligations that make this trait reference /// well-formed. For example, if there is a trait `Set` defined like -/// `trait Set`, then the trait reference `Foo: Set` is WF +/// `trait Set`, then the trait bound `Foo: Set` is WF /// if `Bar: Eq`. pub fn trait_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - trait_pred: &ty::TraitPredicate<'tcx>, + trait_pred: ty::TraitPredicate<'tcx>, span: Span, item: &'tcx hir::Item<'tcx>, ) -> Vec> { @@ -129,12 +129,17 @@ pub fn trait_obligations<'tcx>( wf.normalize(infcx) } +/// Returns the requirements for `clause` to be well-formed. +/// +/// For example, if there is a trait `Set` defined like +/// `trait Set`, then the trait bound `Foo: Set` is WF +/// if `Bar: Eq`. #[instrument(skip(infcx), ret)] -pub fn predicate_obligations<'tcx>( +pub fn clause_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, span: Span, ) -> Vec> { let mut wf = WfPredicates { @@ -148,45 +153,32 @@ pub fn predicate_obligations<'tcx>( }; // It's ok to skip the binder here because wf code is prepared for it - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { - wf.compute_trait_pred(&t, Elaborate::None); + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(t) => { + wf.compute_trait_pred(t, Elaborate::None); } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {} - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - ty, - _reg, - ))) => { + ty::ClauseKind::RegionOutlives(..) => {} + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { wf.compute(ty.into()); } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(t)) => { + ty::ClauseKind::Projection(t) => { wf.compute_projection(t.projection_ty); wf.compute(match t.term.unpack() { ty::TermKind::Ty(ty) => ty.into(), ty::TermKind::Const(c) => c.into(), }) } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + ty::ClauseKind::ConstArgHasType(ct, ty) => { wf.compute(ct.into()); wf.compute(ty.into()); } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + ty::ClauseKind::WellFormed(arg) => { wf.compute(arg); } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { + ty::ClauseKind::ConstEvaluatable(ct) => { wf.compute(ct.into()); } - - ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasRelate(..) => { - bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}") - } } wf.normalize(infcx) @@ -233,7 +225,7 @@ enum Elaborate { fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: &ty::TraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: ty::Predicate<'tcx>, @@ -336,9 +328,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. - fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) { + fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) { let tcx = self.tcx(); - let trait_ref = &trait_pred.trait_ref; + let trait_ref = trait_pred.trait_ref; // Negative trait predicates don't require supertraits to hold, just // that their args are WF. @@ -411,7 +403,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // Compute the obligations that are required for `trait_ref` to be WF, // given that it is a *negative* trait predicate. - fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) { + fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) { for arg in trait_ref.args { self.compute(arg); } @@ -609,7 +601,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { | ty::Error(_) | ty::Str | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Param(_) | ty::Bound(..) diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 6c49e94dc310b..4b55963201717 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -9,7 +9,7 @@ extern crate tracing; pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; pub mod layout; -pub(crate) mod maybe_transmutable; +mod maybe_transmutable; #[derive(Default)] pub struct Assume { @@ -19,7 +19,7 @@ pub struct Assume { pub validity: bool, } -/// Either we have an error, transmutation is allowed, or we have an optional +/// Either transmutation is allowed, we have an error, or we have an optional /// Condition that must hold. #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub enum Answer { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index c0141f1f84149..bf3c390c8008e 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -32,26 +32,6 @@ where ) -> Self { Self { src, dst, scope, assume, context } } - - // FIXME(bryangarza): Delete this when all usages are removed - pub(crate) fn map_layouts( - self, - f: F, - ) -> Result, Answer<::Ref>> - where - F: FnOnce( - L, - L, - ::Scope, - &C, - ) -> Result<(M, M), Answer<::Ref>>, - { - let Self { src, dst, scope, assume, context } = self; - - let (src, dst) = f(src, dst, scope, &context)?; - - Ok(MaybeTransmutableQuery { src, dst, scope, assume, context }) - } } // FIXME: Nix this cfg, so we can write unit tests independently of rustc @@ -107,42 +87,42 @@ where #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))] pub(crate) fn answer(self) -> Answer<::Ref> { let assume_visibility = self.assume.safety; - // FIXME(bryangarza): Refactor this code to get rid of `map_layouts` - let query_or_answer = self.map_layouts(|src, dst, scope, context| { - // Remove all `Def` nodes from `src`, without checking their visibility. - let src = src.prune(&|def| true); - trace!(?src, "pruned src"); + let Self { src, dst, scope, assume, context } = self; - // Remove all `Def` nodes from `dst`, additionally... - let dst = if assume_visibility { - // ...if visibility is assumed, don't check their visibility. - dst.prune(&|def| true) - } else { - // ...otherwise, prune away all unreachable paths through the `Dst` layout. - dst.prune(&|def| context.is_accessible_from(def, scope)) - }; + // Remove all `Def` nodes from `src`, without checking their visibility. + let src = src.prune(&|def| true); - trace!(?dst, "pruned dst"); + trace!(?src, "pruned src"); - // Convert `src` from a tree-based representation to an NFA-based representation. - // If the conversion fails because `src` is uninhabited, conclude that the transmutation - // is acceptable, because instances of the `src` type do not exist. - let src = Nfa::from_tree(src).map_err(|Uninhabited| Answer::Yes)?; + // Remove all `Def` nodes from `dst`, additionally... + let dst = if assume_visibility { + // ...if visibility is assumed, don't check their visibility. + dst.prune(&|def| true) + } else { + // ...otherwise, prune away all unreachable paths through the `Dst` layout. + dst.prune(&|def| context.is_accessible_from(def, scope)) + }; - // Convert `dst` from a tree-based representation to an NFA-based representation. - // If the conversion fails because `src` is uninhabited, conclude that the transmutation - // is unacceptable, because instances of the `dst` type do not exist. - let dst = - Nfa::from_tree(dst).map_err(|Uninhabited| Answer::No(Reason::DstIsPrivate))?; + trace!(?dst, "pruned dst"); - Ok((src, dst)) - }); + // Convert `src` from a tree-based representation to an NFA-based representation. + // If the conversion fails because `src` is uninhabited, conclude that the transmutation + // is acceptable, because instances of the `src` type do not exist. + let src = match Nfa::from_tree(src) { + Ok(src) => src, + Err(Uninhabited) => return Answer::Yes, + }; - match query_or_answer { - Ok(query) => query.answer(), - Err(answer) => answer, - } + // Convert `dst` from a tree-based representation to an NFA-based representation. + // If the conversion fails because `src` is uninhabited, conclude that the transmutation + // is unacceptable, because instances of the `dst` type do not exist. + let dst = match Nfa::from_tree(dst) { + Ok(dst) => dst, + Err(Uninhabited) => return Answer::No(Reason::DstIsPrivate), + }; + + MaybeTransmutableQuery { src, dst, scope, assume, context }.answer() } } @@ -156,14 +136,10 @@ where #[inline(always)] #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))] pub(crate) fn answer(self) -> Answer<::Ref> { - // FIXME(bryangarza): Refactor this code to get rid of `map_layouts` - let query_or_answer = self - .map_layouts(|src, dst, scope, context| Ok((Dfa::from_nfa(src), Dfa::from_nfa(dst)))); - - match query_or_answer { - Ok(query) => query.answer(), - Err(answer) => answer, - } + let Self { src, dst, scope, assume, context } = self; + let src = Dfa::from_nfa(src); + let dst = Dfa::from_nfa(dst); + MaybeTransmutableQuery { src, dst, scope, assume, context }.answer() } } @@ -171,26 +147,8 @@ impl MaybeTransmutableQuery::Ref>, C> where C: QueryContext, { - /// Answers whether a `Nfa` is transmutable into another `Nfa`. - /// - /// This method converts `src` and `dst` to DFAs, then computes an answer using those DFAs. + /// Answers whether a `Dfa` is transmutable into another `Dfa`. pub(crate) fn answer(self) -> Answer<::Ref> { - MaybeTransmutableQuery { - src: &self.src, - dst: &self.dst, - scope: self.scope, - assume: self.assume, - context: self.context, - } - .answer() - } -} - -impl<'l, C> MaybeTransmutableQuery<&'l Dfa<::Ref>, C> -where - C: QueryContext, -{ - pub(crate) fn answer(&mut self) -> Answer<::Ref> { self.answer_memo(&mut Map::default(), self.src.start, self.dst.start) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 16183403d67aa..b118ddaab2b8d 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -528,7 +528,7 @@ fn fn_abi_adjust_for_abi<'tcx>( arg.make_indirect(); } else { // We want to pass small aggregates as immediates, but using - // a LLVM aggregate type for this leads to bad optimizations, + // an LLVM aggregate type for this leads to bad optimizations, // so we pick an appropriately sized integer type instead. arg.cast_to(Reg { kind: RegKind::Integer, size }); } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 383cc996b9e69..35487d3b6982b 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -71,7 +71,7 @@ pub(crate) fn destructure_const<'tcx>( _ => bug!("cannot destructure constant {:?}", const_), }; - let fields = tcx.arena.alloc_from_iter(fields.into_iter()); + let fields = tcx.arena.alloc_from_iter(fields); ty::DestructuredConst { variant, fields } } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 436f10a4f7b91..ec2e0daaf88b2 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -119,7 +119,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { - DefKind::TyAlias { .. } => ty::List::empty(), + DefKind::TyAlias => ty::List::empty(), DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), // Nested opaque types only occur in associated types: // ` type Opaque = impl Trait<&'static T, AssocTy = impl Nested>; ` @@ -136,7 +136,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index a03b82305f069..8132742d1df2b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -85,7 +85,7 @@ fn univariant_uninterned<'tcx>( fields: &IndexSlice>, repr: &ReprOptions, kind: StructKind, -) -> Result> { +) -> Result, &'tcx LayoutError<'tcx>> { let dl = cx.data_layout(); let pack = repr.pack; if pack.is_some() && repr.align.is_some() { @@ -577,11 +577,7 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Infer(_) - | ty::Error(_) => { + ty::Bound(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => { bug!("Layout::compute: unexpected type `{}`", ty) } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 1fc5d9359a48a..6dcbc4470e607 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; use rustc_session::Limit; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::sym; use crate::errors::NeedsDropOverflow; @@ -133,7 +133,7 @@ where // The information required to determine whether a generator has drop is // computed on MIR, while this very method is used to build MIR. // To avoid cycles, we consider that generators always require drop. - ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => { + ty::Generator(..) => { return Some(Err(AlwaysRequiresDrop)); } @@ -145,29 +145,6 @@ where } } - ty::Generator(def_id, args, _) => { - let args = args.as_generator(); - for upvar in args.upvar_tys() { - queue_type(self, upvar); - } - - let witness = args.witness(); - let interior_tys = match witness.kind() { - &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), - _ => { - tcx.sess.delay_span_bug( - tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP), - format!("unexpected generator witness type {witness:?}"), - ); - return Some(Err(AlwaysRequiresDrop)); - } - }; - - for interior_ty in interior_tys { - queue_type(self, interior_ty); - } - } - // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. @@ -215,7 +192,6 @@ where | ty::Tuple(_) | ty::Bound(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Infer(_) | ty::Error(_) => { diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 38768f0a05b6d..06a30677d2005 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -53,9 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent(&self) -> Option { match self.tcx.def_kind(self.item) { - DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias { .. } => { - None - } + DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None, DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { Some(self.tcx.local_parent(self.item)) } @@ -118,7 +116,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[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) { + 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); } @@ -297,7 +295,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ collector.collect_body_and_predicate_taits(); } // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { tcx.type_of(item).instantiate_identity().visit_with(&mut collector); } DefKind::OpaqueTy => { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2288d36df17bd..c22c67bd90750 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -3,9 +3,8 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; -use rustc_middle::ty::{ - self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, -}; +use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitor}; +use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable}; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits; @@ -21,13 +20,7 @@ fn sized_constraint_for_ty<'tcx>( Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![], - Str - | Dynamic(..) - | Slice(_) - | Foreign(..) - | Error(_) - | GeneratorWitness(..) - | GeneratorWitnessMIR(..) => { + Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => { // these are never sized - return the target type vec![ty] } @@ -220,10 +213,10 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // strategy, then just reinterpret the associated type like an opaque :^) let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args); - self.predicates.push(ty::Clause::from_projection_clause(self.tcx, ty::Binder::bind_with_vars( + self.predicates.push(ty::Binder::bind_with_vars( ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, self.bound_vars, - ))); + ).to_predicate(self.tcx)); // We walk the *un-shifted* alias ty, because we're tracking the de bruijn // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd @@ -296,9 +289,12 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option, def_id: LocalDefId) -> hir::IsAsync { +fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Asyncness { let node = tcx.hir().get_by_def_id(def_id); - node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) + node.fn_sig().map_or(ty::Asyncness::No, |sig| match sig.header.asyncness { + hir::IsAsync::Async(_) => ty::Asyncness::Yes, + hir::IsAsync::NotAsync => ty::Asyncness::No, + }) } fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet { diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index b574cdcc879a1..091b51440a6e1 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -143,31 +143,6 @@ pub enum TyKind { /// `GeneratorArgs`. Generator(I::DefId, I::GenericArgsRef, I::Movability), - /// A type representing the types stored inside a generator. - /// This should only appear as part of the `GeneratorArgs`. - /// - /// Note that the captured variables for generators are stored separately - /// using a tuple in the same way as for closures. - /// - /// Unlike upvars, the witness can reference lifetimes from - /// inside of the generator itself. To deal with them in - /// the type of the generator, we convert them to higher ranked - /// lifetimes bound by the witness itself. - /// - /// Looking at the following example, the witness for this generator - /// may end up as something like `for<'a> [Vec, &'a Vec]`: - /// - /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?) - /// #![feature(generators)] - /// |a| { - /// let x = &vec![3]; - /// yield a; - /// yield x[0]; - /// } - /// # ; - /// ``` - GeneratorWitness(I::BinderListTy), - /// A type representing the types stored inside a generator. /// This should only appear as part of the `GeneratorArgs`. /// @@ -192,7 +167,7 @@ pub enum TyKind { /// } /// # ; /// ``` - GeneratorWitnessMIR(I::DefId, I::GenericArgsRef), + GeneratorWitness(I::DefId, I::GenericArgsRef), /// The never type `!`. Never, @@ -278,7 +253,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Dynamic(..) => 14, Closure(_, _) => 15, Generator(_, _, _) => 16, - GeneratorWitness(_) => 17, + GeneratorWitness(_, _) => 17, Never => 18, Tuple(_) => 19, Alias(_, _) => 20, @@ -287,7 +262,6 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Placeholder(_) => 23, Infer(_) => 24, Error(_) => 25, - GeneratorWitnessMIR(_, _) => 26, } } @@ -312,8 +286,7 @@ impl Clone for TyKind { Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr), Closure(d, s) => Closure(d.clone(), s.clone()), Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()), - GeneratorWitness(g) => GeneratorWitness(g.clone()), - GeneratorWitnessMIR(d, s) => GeneratorWitnessMIR(d.clone(), s.clone()), + GeneratorWitness(d, s) => GeneratorWitness(d.clone(), s.clone()), Never => Never, Tuple(t) => Tuple(t.clone()), Alias(k, p) => Alias(*k, p.clone()), @@ -355,10 +328,7 @@ impl PartialEq for TyKind { (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { a_d == b_d && a_s == b_s && a_m == b_m } - (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g, - (GeneratorWitnessMIR(a_d, a_s), GeneratorWitnessMIR(b_d, b_s)) => { - a_d == b_d && a_s == b_s - } + (GeneratorWitness(a_d, a_s), GeneratorWitness(b_d, b_s)) => a_d == b_d && a_s == b_s, (Tuple(a_t), Tuple(b_t)) => a_t == b_t, (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p, (Param(a_p), Param(b_p)) => a_p == b_p, @@ -415,10 +385,9 @@ impl Ord for TyKind { (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m))) } - (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g), ( - GeneratorWitnessMIR(a_d, a_s), - GeneratorWitnessMIR(b_d, b_s), + GeneratorWitness(a_d, a_s), + GeneratorWitness(b_d, b_s), ) => match Ord::cmp(a_d, b_d) { Ordering::Equal => Ord::cmp(a_s, b_s), cmp => cmp, @@ -483,8 +452,7 @@ impl hash::Hash for TyKind { s.hash(state); m.hash(state) } - GeneratorWitness(g) => g.hash(state), - GeneratorWitnessMIR(d, s) => { + GeneratorWitness(d, s) => { d.hash(state); s.hash(state); } @@ -558,28 +526,23 @@ impl DebugWithInfcx for TyKind { }, Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)), Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m), - GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", &this.wrap(g)), - GeneratorWitnessMIR(d, s) => { - f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, &this.wrap(s)) + GeneratorWitness(d, s) => { + f.debug_tuple_field2_finish("GeneratorWitness", d, &this.wrap(s)) } Never => write!(f, "!"), Tuple(t) => { - let mut iter = t.clone().into_iter(); - write!(f, "(")?; - - match iter.next() { - None => return write!(f, ")"), - Some(ty) => write!(f, "{:?}", &this.wrap(ty))?, - }; - - match iter.next() { - None => return write!(f, ",)"), - Some(ty) => write!(f, "{:?})", &this.wrap(ty))?, + let mut count = 0; + for ty in t.clone() { + if count > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", &this.wrap(ty))?; + count += 1; } - - for ty in iter { - write!(f, ", {:?}", &this.wrap(ty))?; + // unary tuples need a trailing comma + if count == 1 { + write!(f, ",")?; } write!(f, ")") } @@ -682,10 +645,7 @@ where args.encode(e); m.encode(e); }), - GeneratorWitness(b) => e.emit_enum_variant(disc, |e| { - b.encode(e); - }), - GeneratorWitnessMIR(def_id, args) => e.emit_enum_variant(disc, |e| { + GeneratorWitness(def_id, args) => e.emit_enum_variant(disc, |e| { def_id.encode(e); args.encode(e); }), @@ -762,7 +722,7 @@ where 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), 15 => Closure(Decodable::decode(d), Decodable::decode(d)), 16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 17 => GeneratorWitness(Decodable::decode(d)), + 17 => GeneratorWitness(Decodable::decode(d), Decodable::decode(d)), 18 => Never, 19 => Tuple(Decodable::decode(d)), 20 => Alias(Decodable::decode(d), Decodable::decode(d)), @@ -771,12 +731,11 @@ where 23 => Placeholder(Decodable::decode(d)), 24 => Infer(Decodable::decode(d)), 25 => Error(Decodable::decode(d)), - 26 => GeneratorWitnessMIR(Decodable::decode(d), Decodable::decode(d)), _ => panic!( "{}", format!( "invalid enum variant tag while decoding `{}`, expected 0..{}", - "TyKind", 27, + "TyKind", 26, ) ), } @@ -870,10 +829,7 @@ where args.hash_stable(__hcx, __hasher); m.hash_stable(__hcx, __hasher); } - GeneratorWitness(b) => { - b.hash_stable(__hcx, __hasher); - } - GeneratorWitnessMIR(def_id, args) => { + GeneratorWitness(def_id, args) => { def_id.hash_stable(__hcx, __hasher); args.hash_stable(__hcx, __hasher); } diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml new file mode 100644 index 0000000000000..c61e217bf9f0a --- /dev/null +++ b/compiler/stable_mir/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "stable_mir" +version = "0.1.0-preview" +edition = "2021" + +[dependencies] +tracing = "0.1" +scoped-tls = "1.0" diff --git a/compiler/rustc_smir/README.md b/compiler/stable_mir/README.md similarity index 100% rename from compiler/rustc_smir/README.md rename to compiler/stable_mir/README.md diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/stable_mir/rust-toolchain.toml similarity index 100% rename from compiler/rustc_smir/rust-toolchain.toml rename to compiler/stable_mir/rust-toolchain.toml diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/stable_mir/src/fold.rs similarity index 89% rename from compiler/rustc_smir/src/stable_mir/fold.rs rename to compiler/stable_mir/src/fold.rs index 831cfb40a1542..6471b2c2a3a5e 100644 --- a/compiler/rustc_smir/src/stable_mir/fold.rs +++ b/compiler/stable_mir/src/fold.rs @@ -1,20 +1,23 @@ use std::ops::ControlFlow; -use crate::rustc_internal::Opaque; +use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind, - GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, + GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, }; pub trait Folder: Sized { type Break; - fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + fn fold_ty(&mut self, ty: &Ty) -> ControlFlow { ty.super_fold(self) } fn fold_const(&mut self, c: &Const) -> ControlFlow { c.super_fold(self) } + fn fold_reg(&mut self, reg: &Region) -> ControlFlow { + reg.super_fold(self) + } } pub trait Foldable: Sized + Clone { @@ -26,7 +29,7 @@ pub trait Foldable: Sized + Clone { impl Foldable for Ty { fn fold(&self, folder: &mut V) -> ControlFlow { - folder.visit_ty(self) + folder.fold_ty(self) } fn super_fold(&self, folder: &mut V) -> ControlFlow { let mut kind = self.kind(); @@ -81,7 +84,7 @@ impl Foldable for UnevaluatedConst { impl Foldable for ConstDef { fn super_fold(&self, _folder: &mut V) -> ControlFlow { - ControlFlow::Continue(self.clone()) + ControlFlow::Continue(*self) } } @@ -96,7 +99,7 @@ impl Foldable for Option { impl Foldable for Promoted { fn super_fold(&self, _folder: &mut V) -> ControlFlow { - ControlFlow::Continue(self.clone()) + ControlFlow::Continue(*self) } } @@ -106,6 +109,15 @@ impl Foldable for GenericArgs { } } +impl Foldable for Region { + fn fold(&self, folder: &mut V) -> ControlFlow { + folder.fold_reg(self) + } + fn super_fold(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + impl Foldable for GenericArgKind { fn super_fold(&self, folder: &mut V) -> ControlFlow { let mut this = self.clone(); @@ -136,7 +148,10 @@ impl Foldable for RigidTy { } RigidTy::Slice(inner) => *inner = inner.fold(folder)?, RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?, - RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?, + RigidTy::Ref(reg, ty, _) => { + *reg = reg.fold(folder)?; + *ty = ty.fold(folder)? + } RigidTy::FnDef(_, args) => *args = args.fold(folder)?, RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?, RigidTy::Closure(_, args) => *args = args.fold(folder)?, @@ -214,7 +229,7 @@ pub enum Never {} impl Folder for GenericArgs { type Break = Never; - fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + fn fold_ty(&mut self, ty: &Ty) -> ControlFlow { ControlFlow::Continue(match ty.kind() { TyKind::Param(p) => self[p], _ => *ty, diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/stable_mir/src/lib.rs similarity index 73% rename from compiler/rustc_smir/src/stable_mir/mod.rs rename to compiler/stable_mir/src/lib.rs index 3c86cb4038a0a..79f598b6faac3 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/stable_mir/src/lib.rs @@ -1,15 +1,21 @@ -//! Module that implements the public interface to the Stable MIR. +//! The WIP stable interface to rustc internals. //! -//! This module shall contain all type definitions and APIs that we expect third-party tools to invoke to -//! interact with the compiler. +//! For more information see //! -//! The goal is to eventually move this module to its own crate which shall be published on -//! [crates.io](https://crates.io). +//! # Note //! -//! ## Note: +//! This API is still completely unstable and subject to change. + +#![doc( + html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", + test(attr(allow(unused_variables), deny(warnings))) +)] //! -//! There shouldn't be any direct references to internal compiler constructs in this module. -//! If you need an internal construct, consider using `rustc_internal` or `rustc_smir`. +//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to +//! interact with the compiler. +//! +//! The goal is to eventually be published on +//! [crates.io](https://crates.io). use std::cell::Cell; use std::fmt; @@ -18,7 +24,9 @@ use std::fmt::Debug; use self::ty::{ GenericPredicates, Generics, ImplDef, ImplTrait, Span, TraitDecl, TraitDef, Ty, TyKind, }; -use crate::rustc_smir::Tables; + +#[macro_use] +extern crate scoped_tls; pub mod fold; pub mod mir; @@ -33,11 +41,11 @@ pub type CrateNum = usize; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq)] -pub struct DefId(pub(crate) usize); +pub struct DefId(pub usize); impl Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DefId:") + f.debug_struct("DefId") .field("id", &self.0) .field("name", &with(|cx| cx.name_of_def_id(*self))) .finish() @@ -46,7 +54,7 @@ impl Debug for DefId { /// A unique identification number for each provenance #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AllocId(pub(crate) usize); +pub struct AllocId(pub usize); /// A list of crate items. pub type CrateItems = Vec; @@ -74,16 +82,18 @@ pub enum CompilerError { /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { - pub(crate) id: CrateNum, + pub id: CrateNum, pub name: Symbol, pub is_local: bool, } +pub type DefKind = Opaque; + /// Holds information about an item in the crate. /// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to /// use this item. #[derive(Clone, PartialEq, Eq, Debug)] -pub struct CrateItem(pub(crate) DefId); +pub struct CrateItem(pub DefId); impl CrateItem { pub fn body(&self) -> mir::Body { @@ -93,6 +103,14 @@ impl CrateItem { pub fn span(&self) -> Span { with(|cx| cx.span_of_an_item(self.0)) } + + pub fn name(&self) -> String { + with(|cx| cx.name_of_def_id(self.0)) + } + + pub fn kind(&self) -> DefKind { + with(|cx| cx.def_kind(self.0)) + } } /// Return the function where execution starts if the current @@ -107,9 +125,9 @@ pub fn local_crate() -> Crate { with(|cx| cx.local_crate()) } -/// Try to find a crate with the given name. -pub fn find_crate(name: &str) -> Option { - with(|cx| cx.find_crate(name)) +/// Try to find a crate or crates if multiple crates exist from given name. +pub fn find_crates(name: &str) -> Vec { + with(|cx| cx.find_crates(name)) } /// Try to find a crate with the given name. @@ -156,11 +174,17 @@ pub trait Context { fn external_crates(&self) -> Vec; /// Find a crate with the given name. - fn find_crate(&self, name: &str) -> Option; + fn find_crates(&self, name: &str) -> Vec; /// Prints the name of given `DefId` fn name_of_def_id(&self, def_id: DefId) -> String; + /// Prints a human readable form of `Span` + fn print_span(&self, span: Span) -> String; + + /// Prints the kind of given `DefId` + fn def_kind(&mut self, def_id: DefId) -> DefKind; + /// `Span` of an item fn span_of_an_item(&mut self, def_id: DefId) -> Span; @@ -169,10 +193,6 @@ pub trait Context { /// Create a new `Ty` from scratch without information from rustc. fn mk_ty(&mut self, kind: TyKind) -> Ty; - - /// HACK: Until we have fully stable consumers, we need an escape hatch - /// to get `DefId`s out of `CrateItem`s. - fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)); } // A thread local variable that stores a pointer to the tables mapping between TyCtxt @@ -192,7 +212,7 @@ 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(f: impl FnOnce(&mut dyn Context) -> R) -> R { +pub fn with(f: impl FnOnce(&mut dyn Context) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); @@ -200,3 +220,23 @@ pub(crate) fn with(f: impl FnOnce(&mut dyn Context) -> R) -> R { f(unsafe { *(ptr as *mut &mut dyn Context) }) }) } + +/// A type that provides internal information but that can still be used for debug purpose. +#[derive(Clone)] +pub struct Opaque(String); + +impl std::fmt::Display for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } +} + +pub fn opaque(value: &T) -> Opaque { + Opaque(format!("{value:?}")) +} diff --git a/compiler/rustc_smir/src/stable_mir/mir.rs b/compiler/stable_mir/src/mir.rs similarity index 100% rename from compiler/rustc_smir/src/stable_mir/mir.rs rename to compiler/stable_mir/src/mir.rs diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/stable_mir/src/mir/body.rs similarity index 93% rename from compiler/rustc_smir/src/stable_mir/mir/body.rs rename to compiler/stable_mir/src/mir/body.rs index 449ca4b8145ed..72f026ee8de09 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,13 +1,17 @@ -use crate::rustc_internal::Opaque; -use crate::stable_mir::ty::{ - AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, -}; -use crate::stable_mir::{self, ty::Ty, Span}; +use crate::ty::{AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region}; +use crate::Opaque; +use crate::{ty::Ty, Span}; #[derive(Clone, Debug)] pub struct Body { pub blocks: Vec, - pub locals: Vec, + pub locals: Vec, +} + +#[derive(Clone, Debug)] +pub struct LocalDecl { + pub ty: Ty, + pub span: Span, } #[derive(Clone, Debug)] @@ -17,7 +21,13 @@ pub struct BasicBlock { } #[derive(Clone, Debug)] -pub enum Terminator { +pub struct Terminator { + pub kind: TerminatorKind, + pub span: Span, +} + +#[derive(Clone, Debug)] +pub enum TerminatorKind { Goto { target: usize, }, @@ -135,7 +145,7 @@ pub enum AsyncGeneratorKind { } pub(crate) type LocalDefId = Opaque; -/// [`rustc_middle::mir::Coverage`] is heavily tied to internal details of the +/// The rustc coverage data structures are heavily tied to internal details of the /// coverage implementation that are likely to change, and are unlikely to be /// useful to third-party tools for the foreseeable future. pub(crate) type Coverage = Opaque; @@ -181,7 +191,13 @@ pub enum NonDivergingIntrinsic { } #[derive(Clone, Debug)] -pub enum Statement { +pub struct Statement { + pub kind: StatementKind, + pub span: Span, +} + +#[derive(Clone, Debug)] +pub enum StatementKind { Assign(Place, Rvalue), FakeRead(FakeReadCause, Place), SetDiscriminant { place: Place, variant_index: VariantIdx }, @@ -215,7 +231,7 @@ pub enum Rvalue { /// generator lowering, `Generator` aggregate kinds are disallowed too. Aggregate(AggregateKind, Vec), - /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second + /// * `Offset` has the same semantics as `<*const T>::offset`, except that the second /// parameter may be a `usize` as well. /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, /// raw pointers, or function pointers and return a `bool`. The types of the operands must be @@ -245,16 +261,14 @@ pub enum Rvalue { /// deref operation, immediately followed by one or more projections. CopyForDeref(Place), - /// Computes the discriminant of the place, returning it as an integer of type - /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// Computes the discriminant of the place, returning it as an integer. + /// Returns zero for types without discriminant. /// /// The validity requirements for the underlying value are undecided for this rvalue, see /// [#91095]. Note too that the value of the discriminant is not the same thing as the - /// variant index; use [`discriminant_for_variant`] to convert. + /// variant index; /// - /// [`discriminant_ty`]: rustc_middle::ty::Ty::discriminant_ty /// [#91095]: https://github.com/rust-lang/rust/issues/91095 - /// [`discriminant_for_variant`]: rustc_middle::ty::Ty::discriminant_for_variant Discriminant(Place), /// Yields the length of the place, as a `usize`. @@ -295,7 +309,7 @@ pub enum Rvalue { /// /// **Needs clarification**: Are there weird additional semantics here related to the runtime /// nature of this operation? - ThreadLocalRef(stable_mir::CrateItem), + ThreadLocalRef(crate::CrateItem), /// Computes a value as described by the operation. NullaryOp(NullOp, Ty), diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/stable_mir/src/ty.rs similarity index 87% rename from compiler/rustc_smir/src/stable_mir/ty.rs rename to compiler/stable_mir/src/ty.rs index 3a8fc1a502e6d..6029e3c11adef 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1,9 +1,9 @@ use super::{ mir::Safety, mir::{Body, Mutability}, - with, AllocId, DefId, + with, AllocId, DefId, Symbol, }; -use crate::rustc_internal::Opaque; +use crate::Opaque; use std::fmt::{self, Debug, Formatter}; #[derive(Copy, Clone)] @@ -34,15 +34,55 @@ pub struct Const { } type Ident = Opaque; -pub(crate) type Region = Opaque; + +#[derive(Debug, Clone)] +pub struct Region { + pub kind: RegionKind, +} + +#[derive(Debug, Clone)] +pub enum RegionKind { + ReEarlyBound(EarlyBoundRegion), + ReLateBound(DebruijnIndex, BoundRegion), + ReStatic, + RePlaceholder(Placeholder), + ReErased, +} + +pub(crate) type DebruijnIndex = u32; + +#[derive(Debug, Clone)] +pub struct EarlyBoundRegion { + pub def_id: RegionDef, + pub index: u32, + pub name: Symbol, +} + +pub(crate) type BoundVar = u32; + +#[derive(Debug, Clone)] +pub struct BoundRegion { + pub var: BoundVar, + pub kind: BoundRegionKind, +} + +pub(crate) type UniverseIndex = u32; + +#[derive(Debug, Clone)] +pub struct Placeholder { + pub universe: UniverseIndex, + pub bound: T, +} + #[derive(Clone, Copy, PartialEq, Eq)] -pub struct Span(pub(crate) usize); +pub struct Span(pub usize); impl Debug for Span { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let mut span = None; - with(|context| context.rustc_tables(&mut |tables| span = Some(tables.spans[self.0]))); - f.write_fmt(format_args!("{:?}", &span.unwrap())) + f.debug_struct("Span") + .field("id", &self.0) + .field("repr", &with(|cx| cx.print_span(*self))) + .finish() } } @@ -110,10 +150,10 @@ pub enum Movability { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ForeignDef(pub(crate) DefId); +pub struct ForeignDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct FnDef(pub(crate) DefId); +pub struct FnDef(pub DefId); impl FnDef { pub fn body(&self) -> Body { @@ -122,34 +162,37 @@ impl FnDef { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ClosureDef(pub(crate) DefId); +pub struct ClosureDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct GeneratorDef(pub(crate) DefId); +pub struct GeneratorDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ParamDef(pub(crate) DefId); +pub struct ParamDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct BrNamedDef(pub(crate) DefId); +pub struct BrNamedDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AdtDef(pub(crate) DefId); +pub struct AdtDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AliasDef(pub(crate) DefId); +pub struct AliasDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct TraitDef(pub(crate) DefId); +pub struct TraitDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct GenericDef(pub(crate) DefId); +pub struct GenericDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ConstDef(pub(crate) DefId); +pub struct ConstDef(pub DefId); + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ImplDef(pub DefId); #[derive(Clone, PartialEq, Eq, Debug)] -pub struct ImplDef(pub(crate) DefId); +pub struct RegionDef(pub DefId); #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); @@ -286,7 +329,7 @@ pub enum BoundTyKind { #[derive(Clone, Debug)] pub enum BoundRegionKind { - BrAnon(Option), + BrAnon, BrNamed(BrNamedDef, String), BrEnv, } @@ -333,7 +376,7 @@ pub type Bytes = Vec>; pub type Size = usize; #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Prov(pub(crate) AllocId); +pub struct Prov(pub AllocId); pub type Align = u64; pub type Promoted = u32; pub type InitMaskMaterialized = Vec; diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/stable_mir/src/visitor.rs similarity index 90% rename from compiler/rustc_smir/src/stable_mir/visitor.rs rename to compiler/stable_mir/src/visitor.rs index c86063d2ed6eb..961009581388d 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -1,10 +1,10 @@ use std::ops::ControlFlow; -use crate::rustc_internal::Opaque; +use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - Promoted, RigidTy, TermKind, Ty, UnevaluatedConst, + Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; pub trait Visitor: Sized { @@ -15,6 +15,9 @@ pub trait Visitor: Sized { fn visit_const(&mut self, c: &Const) -> ControlFlow { c.super_visit(self) } + fn visit_reg(&mut self, reg: &Region) -> ControlFlow { + reg.super_visit(self) + } } pub trait Visitable { @@ -101,6 +104,16 @@ impl Visitable for GenericArgs { } } +impl Visitable for Region { + fn visit(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_reg(self) + } + + fn super_visit(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + impl Visitable for GenericArgKind { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { @@ -128,7 +141,10 @@ impl Visitable for RigidTy { } RigidTy::Slice(inner) => inner.visit(visitor), RigidTy::RawPtr(ty, _) => ty.visit(visitor), - RigidTy::Ref(_, ty, _) => ty.visit(visitor), + RigidTy::Ref(reg, ty, _) => { + reg.visit(visitor); + ty.visit(visitor) + } RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Closure(_, args) => args.visit(visitor), diff --git a/config.example.toml b/config.example.toml index f3c2366d674ea..4f44121410ecd 100644 --- a/config.example.toml +++ b/config.example.toml @@ -19,11 +19,18 @@ # Note that this has no default value (x.py uses the defaults in `config.example.toml`). #profile = -# Keeps track of the last version of `x.py` used. -# If `changelog-seen` does not match the version that is currently running, -# `x.py` will prompt you to update it and to read the changelog. -# See `src/bootstrap/CHANGELOG.md` for more information. -changelog-seen = 2 +# Keeps track of major changes made to this configuration. +# +# This value also represents ID of the PR that caused major changes. Meaning, +# you can visit github.com/rust-lang/rust/pull/{change-id} to check for more details. +# +# A 'major change' includes any of the following +# - A new option +# - A change in the default values +# +# If `change-id` does not match the version that is currently running, +# `x.py` will prompt you to update it and check the related PR for more details. +change-id = 115898 # ============================================================================= # Tweaking how LLVM is compiled diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 84331eba2d49d..b6b6246baa670 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -55,6 +55,7 @@ pub trait ToOwned { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "cloning is often expensive and is not expected to have side effects"] + #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")] fn to_owned(&self) -> Self::Owned; /// Uses borrowed data to replace owned data, usually by cloning. diff --git a/library/alloc/src/collections/btree/dedup_sorted_iter.rs b/library/alloc/src/collections/btree/dedup_sorted_iter.rs index 17ee78045a9b2..cd6a88f329125 100644 --- a/library/alloc/src/collections/btree/dedup_sorted_iter.rs +++ b/library/alloc/src/collections/btree/dedup_sorted_iter.rs @@ -1,6 +1,6 @@ use core::iter::Peekable; -/// A iterator for deduping the key of a sorted iterator. +/// An iterator for deduping the key of a sorted iterator. /// When encountering the duplicated key, only the last key-value pair is yielded. /// /// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1]. diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f435f503fc160..cd3648214a48c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,6 +140,7 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(pattern)] #![feature(pointer_byte_offsets)] +#![feature(ptr_addr_eq)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0fb06b16655b3..73cb746c41d0a 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1649,7 +1649,7 @@ impl Rc { /// assert!(!Rc::ptr_eq(&five, &other_five)); /// ``` pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const () + ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) } } @@ -2408,6 +2408,27 @@ impl From for Rc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "CURRENT_RUSTC_VERSION")] +impl From<[T; N]> for Rc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Rc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Rc`. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Rc<[T]> { + Rc::<[T; N]>::from(v) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Rc<[T]> { @@ -2680,6 +2701,7 @@ impl> ToRcSlice for I { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "rc_weak", since = "1.4.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, @@ -3125,7 +3147,7 @@ impl Weak { #[must_use] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { - ptr::eq(self.ptr.as_ptr() as *const (), other.ptr.as_ptr() as *const ()) + ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index ed43244ebda19..e42bed7d26444 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2435,6 +2435,7 @@ pub trait ToString { /// ``` #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] fn to_string(&self) -> String; } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c53e9a5dd7abe..0c6f3ef9b7333 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -311,6 +311,7 @@ impl Arc { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "arc_weak", since = "1.4.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, @@ -1618,7 +1619,7 @@ impl Arc { #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn weak_count(this: &Self) -> usize { - let cnt = this.inner().weak.load(Acquire); + let cnt = this.inner().weak.load(Relaxed); // If the weak count is currently locked, the value of the // count was 0 just before taking the lock. if cnt == usize::MAX { 0 } else { cnt - 1 } @@ -1648,7 +1649,7 @@ impl Arc { #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn strong_count(this: &Self) -> usize { - this.inner().strong.load(Acquire) + this.inner().strong.load(Relaxed) } /// Increments the strong reference count on the `Arc` associated with the @@ -1778,7 +1779,7 @@ impl Arc { #[must_use] #[stable(feature = "ptr_eq", since = "1.17.0")] pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const () + ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) } } @@ -2803,7 +2804,7 @@ impl Weak { #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { - if let Some(inner) = self.inner() { inner.strong.load(Acquire) } else { 0 } + if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 } } /// Gets an approximation of the number of `Weak` pointers pointing to this @@ -2822,7 +2823,7 @@ impl Weak { pub fn weak_count(&self) -> usize { if let Some(inner) = self.inner() { let weak = inner.weak.load(Acquire); - let strong = inner.strong.load(Acquire); + let strong = inner.strong.load(Relaxed); if strong == 0 { 0 } else { @@ -2900,7 +2901,7 @@ impl Weak { #[must_use] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { - ptr::eq(self.ptr.as_ptr() as *const (), other.ptr.as_ptr() as *const ()) + ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) } } @@ -3269,6 +3270,27 @@ impl From for Arc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "CURRENT_RUSTC_VERSION")] +impl From<[T; N]> for Arc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Arc`. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Arc<[T]> { + Arc::<[T; N]>::from(v) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Arc<[T]> { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 02331db33412b..6f0cd5316a082 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3154,6 +3154,36 @@ impl From<&mut [T]> for Vec { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +impl From<&[T; N]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); + /// ``` + fn from(s: &[T; N]) -> Vec { + Self::from(s.as_slice()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut [T; N]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); + /// ``` + fn from(s: &mut [T; N]) -> Vec { + Self::from(s.as_mut_slice()) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_array", since = "1.44.0")] impl From<[T; N]> for Vec { diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 9cb27899f1091..d44dcfbf67301 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2562,3 +2562,13 @@ fn test_box_zero_allocator() { // Ensure all ZSTs have been freed. assert!(alloc.state.borrow().0.is_empty()); } + +#[test] +fn test_vec_from_array_ref() { + assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); +} + +#[test] +fn test_vec_from_array_mut_ref() { + assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); +} diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 587877dff552f..8815cb21fc49d 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -13,6 +13,7 @@ use crate::{ /// A by-value [array] iterator. #[stable(feature = "array_value_iter", since = "1.51.0")] #[rustc_insignificant_dtor] +#[rustc_diagnostic_item = "ArrayIntoIter"] pub struct IntoIter { /// This is the array we are iterating over. /// diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 3b4d99221f295..db07ef7e3c96f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1423,6 +1423,7 @@ impl Clone for BorrowRef<'_> { /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"] +#[rustc_diagnostic_item = "RefCellRef"] pub struct Ref<'b, T: ?Sized + 'b> { // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a // `Ref` argument doesn't hold immutability for its whole scope, only until it drops. @@ -1804,6 +1805,7 @@ impl<'b> BorrowRefMut<'b> { /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"] +#[rustc_diagnostic_item = "RefCellRefMut"] pub struct RefMut<'b, T: ?Sized + 'b> { // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops. diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 33226b07e0427..ca4e6be71efa1 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -3,14 +3,17 @@ //! This module contains various tools for comparing and ordering values. In //! summary: //! -//! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and -//! partial equality between values, respectively. Implementing them overloads -//! the `==` and `!=` operators. +//! * [`PartialEq`] overloads the `==` and `!=` operators. In cases where +//! `Rhs` (the right hand side's type) is `Self`, this trait corresponds to a +//! partial equivalence relation. +//! * [`Eq`] indicates that the overloaded `==` operator corresponds to an +//! equivalence relation. //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and //! partial orderings between values, respectively. Implementing them overloads //! the `<`, `<=`, `>`, and `>=` operators. //! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and -//! [`PartialOrd`], and describes an ordering. +//! [`PartialOrd`], and describes an ordering of two values (less, equal, or +//! greater). //! * [`Reverse`] is a struct that allows you to easily reverse an ordering. //! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you //! to find the maximum or minimum of two values. @@ -27,16 +30,21 @@ pub(crate) use bytewise::BytewiseEq; use self::Ordering::*; -/// Trait for equality comparisons. +/// Trait for comparisons using the equality operator. +/// +/// Implementing this trait for types provides the `==` and `!=` operators for +/// those types. /// /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`. /// We use the easier-to-read infix notation in the remainder of this documentation. /// -/// This trait allows for partial equality, for types that do not have a full -/// equivalence relation. For example, in floating point numbers `NaN != NaN`, -/// so floating point types implement `PartialEq` but not [`trait@Eq`]. -/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence -/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation). +/// This trait allows for comparisons using the equality operator, for types +/// that do not have a full equivalence relation. For example, in floating point +/// numbers `NaN != NaN`, so floating point types implement `PartialEq` but not +/// [`trait@Eq`]. Formally speaking, when `Rhs == Self`, this trait corresponds +/// to a [partial equivalence relation]. +/// +/// [partial equivalence relation]: https://en.wikipedia.org/wiki/Partial_equivalence_relation /// /// Implementations must ensure that `eq` and `ne` are consistent with each other: /// @@ -242,15 +250,15 @@ pub macro PartialEq($item:item) { /* compiler built-in */ } -/// Trait for equality comparisons which are [equivalence relations]( +/// Trait for comparisons corresponding to [equivalence relations]( /// https://en.wikipedia.org/wiki/Equivalence_relation). /// -/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must -/// be (for all `a`, `b` and `c`): +/// This means, that in addition to `a == b` and `a != b` being strict inverses, +/// the relation must be (for all `a`, `b` and `c`): /// /// - reflexive: `a == a`; -/// - symmetric: `a == b` implies `b == a`; and -/// - transitive: `a == b` and `b == c` implies `a == c`. +/// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as well); and +/// - transitive: `a == b` and `b == c` implies `a == c` (required by `PartialEq` as well). /// /// This property cannot be checked by the compiler, and therefore `Eq` implies /// [`PartialEq`], and has no extra methods. @@ -260,6 +268,10 @@ pub macro PartialEq($item:item) { /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these /// methods. /// +/// Implement `Eq` in addition to `PartialEq` if it's guaranteed that +/// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in addition to +/// the symmetric and transitive properties already required by `PartialEq`. +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has @@ -291,9 +303,9 @@ pub macro PartialEq($item:item) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Eq"] pub trait Eq: PartialEq { - // this method is used solely by #[deriving] to assert - // that every component of a type implements #[deriving] - // itself, the current deriving infrastructure means doing this + // this method is used solely by #[derive(Eq)] to assert + // that every component of a type implements `Eq` + // itself. The current deriving infrastructure means doing this // assertion without using a method on this trait is nearly // impossible. // @@ -676,12 +688,19 @@ impl Clone for Reverse { /// /// ## Corollaries /// -/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order. -/// This means that for all `a`, `b` and `c`: +/// From the above and the requirements of `PartialOrd`, it follows that for +/// all `a`, `b` and `c`: /// /// - exactly one of `a < b`, `a == b` or `a > b` is true; and /// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. /// +/// Mathematically speaking, the `<` operator defines a strict [weak order]. In +/// cases where `==` conforms to mathematical equality, it also defines a +/// strict [total order]. +/// +/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering +/// [total order]: https://en.wikipedia.org/wiki/Total_order +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. @@ -790,6 +809,7 @@ pub trait Ord: Eq + PartialOrd { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "ord_cmp_method"] fn cmp(&self, other: &Self) -> Ordering; /// Compares and returns the maximum of two values. @@ -920,6 +940,20 @@ pub macro Ord($item:item) { /// - transitivity of `>`: if `a > b` and `b > c` then `a > c` /// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)` /// +/// ## Strict and non-strict partial orders +/// +/// The `<` and `>` operators behave according to a *strict* partial order. +/// However, `<=` and `>=` do **not** behave according to a *non-strict* +/// partial order. +/// That is because mathematically, a non-strict partial order would require +/// reflexivity, i.e. `a <= a` would need to be true for every `a`. This isn't +/// always the case for types that implement `PartialOrd`, for example: +/// +/// ``` +/// let a = f64::sqrt(-1.0); +/// assert_eq!(a <= a, false); +/// ``` +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index ff5a4c913b7ed..fc8d19d1a58e2 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -100,6 +100,7 @@ pub use num::FloatToInt; #[stable(feature = "convert_id", since = "1.33.0")] #[rustc_const_stable(feature = "const_identity", since = "1.33.0")] #[inline(always)] +#[rustc_diagnostic_item = "convert_identity"] pub const fn identity(x: T) -> T { x } @@ -478,6 +479,46 @@ pub trait Into: Sized { /// - `From for U` implies [`Into`]` for T` /// - `From` is reflexive, which means that `From for T` is implemented /// +/// # When to implement `From` +/// +/// While there's no technical restrictions on which conversions can be done using +/// a `From` implementation, the general expectation is that the conversions +/// should typically be restricted as follows: +/// +/// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`] +/// instead; don't provide a `From` impl that panics. +/// +/// * The conversion is *lossless*: semantically, it should not lose or discard +/// information. For example, `i32: From` exists, where the original +/// value can be recovered using `u16: TryFrom`. And `String: From<&str>` +/// exists, where you can get something equivalent to the original value via +/// `Deref`. But `From` cannot be used to convert from `u32` to `u16`, since +/// that cannot succeed in a lossless way. (There's some wiggle room here for +/// information not considered semantically relevant. For example, +/// `Box<[T]>: From>` exists even though it might not preserve capacity, +/// like how two vectors can be equal despite differing capacities.) +/// +/// * The conversion is *value-preserving*: the conceptual kind and meaning of +/// the resulting value is the same, even though the Rust type and technical +/// representation might be different. For example `-1_i8 as u8` is *lossless*, +/// since `as` casting back can recover the original value, but that conversion +/// is *not* available via `From` because `-1` and `255` are different conceptual +/// values (despite being identical bit patterns technically). But +/// `f32: From` *is* available because `1_i16` and `1.0_f32` are conceptually +/// the same real number (despite having very different bit patterns technically). +/// `String: From` is available because they're both *text*, but +/// `String: From` is *not* available, since `1` (a number) and `"1"` +/// (text) are too different. (Converting values to text is instead covered +/// by the [`Display`](crate::fmt::Display) trait.) +/// +/// * The conversion is *obvious*: it's the only reasonable conversion between +/// the two types. Otherwise it's better to have it be a named method or +/// constructor, like how [`str::as_bytes`] is a method and how integers have +/// methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and +/// [`u32::from_be_bytes`], none of which are `From` implementations. Whereas +/// there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr) +/// into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From` exists. +/// /// # Examples /// /// [`String`] implements `From<&str>`: @@ -642,6 +683,7 @@ pub trait TryFrom: Sized { /// Performs the conversion. #[stable(feature = "try_from", since = "1.34.0")] + #[rustc_diagnostic_item = "try_from_fn"] fn try_from(value: T) -> Result; } diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 5242e97eb9aed..16618b38769d2 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -130,6 +130,7 @@ pub trait Default: Sized { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "default_fn"] fn default() -> Self; } diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 9227248041e91..47db53ac6f34b 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -84,6 +84,7 @@ impl fmt::Write for PadAdapter<'_, '_> { #[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] +#[rustc_diagnostic_item = "DebugStruct"] pub struct DebugStruct<'a, 'b: 'a> { fmt: &'a mut fmt::Formatter<'b>, result: fmt::Result, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 8204b3855bd7e..c45ab094a20d6 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -112,9 +112,9 @@ pub trait Write { /// /// # Errors /// - /// This function will return an instance of [`Error`] on error. + /// This function will return an instance of [`std::fmt::Error`][Error] on error. /// - /// The purpose of std::fmt::Error is to abort the formatting operation when the underlying + /// The purpose of that error is to abort the formatting operation when the underlying /// destination encounters some error preventing it from accepting more text; it should /// generally be propagated rather than handled, at least when implementing formatting traits. /// @@ -239,6 +239,7 @@ impl Write for &mut W { /// documentation of the methods defined on `Formatter` below. #[allow(missing_debug_implementations)] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Formatter"] pub struct Formatter<'a> { flags: u32, fill: char, @@ -791,8 +792,10 @@ pub trait Octal { /// assert_eq!(format!("l as binary is: {l:b}"), "l as binary is: 1101011"); /// /// assert_eq!( -/// format!("l as binary is: {l:#032b}"), -/// "l as binary is: 0b000000000000000000000001101011" +/// // Note that the `0b` prefix added by `#` is included in the total width, so we +/// // need to add two to correctly display all 32 bits. +/// format!("l as binary is: {l:#034b}"), +/// "l as binary is: 0b00000000000000000000000001101011" /// ); /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d37888c27bde3..5bf221b429fac 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -133,6 +133,10 @@ impl<'a> Argument<'a> { Self::new(x, USIZE_MARKER) } + // FIXME: Transmuting formatter in new and indirectly branching to/calling + // it here is an explicit CFI violation. + #[allow(inline_no_sanitize)] + #[no_sanitize(cfi, kcfi)] #[inline(always)] pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result { (self.formatter)(self.value, f) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 4bf3da07354fc..ff177c70d39c9 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -277,7 +277,7 @@ pub fn spin_loop() { /// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot /// optimize this away /// -/// This makes our benchmark much more realistic to how the function would be used in situ, where +/// This makes our benchmark much more realistic to how the function would actually be used, where /// arguments are usually not known at compile time and the result is used in some way. #[inline] #[stable(feature = "bench_black_box", since = "1.66.0")] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 4c76662ac0975..e4d6c2c2928d3 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1509,12 +1509,14 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_nounwind] + #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] pub fn unaligned_volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// The pointer is not required to be aligned. /// /// This intrinsic does not have a stable counterpart. #[rustc_nounwind] + #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] pub fn unaligned_volatile_store(dst: *mut T, val: T); /// Returns the square root of an `f32` @@ -2666,6 +2668,7 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] @@ -2761,6 +2764,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] @@ -2834,6 +2838,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 20aca323bab79..65ba42920c93d 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -12,6 +12,7 @@ use crate::ops::{ControlFlow, Try}; #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "IterPeekable"] pub struct Peekable { iter: I, /// Remember a peeked value, even if it was None. diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 243df015f9a26..438e046a4dfdc 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -27,6 +27,7 @@ pub const fn empty() -> Empty { /// This `struct` is created by the [`empty()`] function. See its documentation for more. #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iter_empty", since = "1.2.0")] +#[rustc_diagnostic_item = "IterEmpty"] pub struct Empty(marker::PhantomData T>); #[stable(feature = "core_impl_debug", since = "1.9.0")] diff --git a/library/core/src/iter/sources/once.rs b/library/core/src/iter/sources/once.rs index 6e9ed0d3c5278..21be4377da1ca 100644 --- a/library/core/src/iter/sources/once.rs +++ b/library/core/src/iter/sources/once.rs @@ -61,6 +61,7 @@ pub fn once(value: T) -> Once { /// This `struct` is created by the [`once()`] function. See its documentation for more. #[derive(Clone, Debug)] #[stable(feature = "iter_once", since = "1.2.0")] +#[rustc_diagnostic_item = "IterOnce"] pub struct Once { inner: crate::option::IntoIter, } diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs index 6a6cbe905e464..7f7b2c7756628 100644 --- a/library/core/src/iter/sources/successors.rs +++ b/library/core/src/iter/sources/successors.rs @@ -17,7 +17,7 @@ where F: FnMut(&T) -> Option, { // If this function returned `impl Iterator` - // it could be based on `unfold` and not need a dedicated type. + // it could be based on `from_fn` and not need a dedicated type. // However having a named `Successors` type allows it to be `Clone` when `T` and `F` are. Successors { next: first, succ } } diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e0ef5071c408a..0d1cf7941fb69 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -146,6 +146,7 @@ pub trait FromIterator: Sized { /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "from_iter_fn"] fn from_iter>(iter: T) -> Self; } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b5458e667ed5f..7fa7e83a74429 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -178,6 +178,7 @@ #![feature(ip)] #![feature(ip_bits)] #![feature(is_ascii_octdigit)] +#![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] @@ -195,6 +196,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), feature(effects))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -236,6 +238,7 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(repr_simd)] @@ -416,6 +419,7 @@ pub mod primitive; // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. #[allow(clashing_extern_declarations)] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] #[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 646100fe27b75..c367b53b72027 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -321,6 +321,95 @@ pub macro debug_assert_matches($($arg:tt)*) { } } +/// A macro for defining `#[cfg]` match-like statements. +/// +/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of +/// `#[cfg]` cases, emitting the implementation which matches first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code +/// without having to rewrite each clause multiple times. +/// +/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when +/// all previous declarations do not evaluate to true. +/// +/// # Example +/// +/// ``` +/// #![feature(cfg_match)] +/// +/// cfg_match! { +/// cfg(unix) => { +/// fn foo() { /* unix specific functionality */ } +/// } +/// cfg(target_pointer_width = "32") => { +/// fn foo() { /* non-unix, 32-bit functionality */ } +/// } +/// _ => { +/// fn foo() { /* fallback implementation */ } +/// } +/// } +/// ``` +#[macro_export] +#[unstable(feature = "cfg_match", issue = "115585")] +#[rustc_diagnostic_item = "cfg_match"] +macro_rules! cfg_match { + // with a final wildcard + ( + $(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+ + _ => { $($extra_tokens:item)* } + ) => { + cfg_match! { + @__items (); + $((($initial_meta) ($($initial_tokens)*)),)+ + (() ($($extra_tokens)*)), + } + }; + + // without a final wildcard + ( + $(cfg($extra_meta:meta) => { $($extra_tokens:item)* })* + ) => { + cfg_match! { + @__items (); + $((($extra_meta) ($($extra_tokens)*)),)* + } + }; + + // Internal and recursive macro to emit all the items + // + // Collects all the previous cfgs in a list at the beginning, so they can be + // negated. After the semicolon is all the remaining items. + (@__items ($($_:meta,)*);) => {}; + ( + @__items ($($no:meta,)*); + (($($yes:meta)?) ($($tokens:item)*)), + $($rest:tt,)* + ) => { + // Emit all items within one block, applying an appropriate #[cfg]. The + // #[cfg] will require all `$yes` matchers specified and must also negate + // all previous matchers. + #[cfg(all( + $($yes,)? + not(any($($no),*)) + ))] + cfg_match! { @__identity $($tokens)* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$yes` matchers to the list of `$no` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_match! { + @__items ($($no,)* $($yes,)?); + $($rest,)* + } + }; + + // Internal macro to make __apply work out right for different match types, + // because of how macros match/expand stuff. + (@__identity $($tokens:item)*) => { + $($tokens)* + }; +} + /// Returns whether the given expression matches any of the given patterns. /// /// Like in a `match` expression, the pattern can be optionally followed by `if` @@ -630,7 +719,8 @@ macro_rules! unreachable { /// The difference between `unimplemented!` and [`todo!`] is that while `todo!` /// conveys an intent of implementing the functionality later and the message is "not yet /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented". -/// Also some IDEs will mark `todo!`s. +/// +/// Also, some IDEs will mark `todo!`s. /// /// # Panics /// @@ -716,11 +806,15 @@ macro_rules! unimplemented { /// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys /// an intent of implementing the functionality later and the message is "not yet /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented". -/// Also some IDEs will mark `todo!`s. +/// +/// Also, some IDEs will mark `todo!`s. /// /// # Panics /// -/// This will always [`panic!`]. +/// This will always [`panic!`] because `todo!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. /// /// # Examples /// @@ -728,38 +822,47 @@ macro_rules! unimplemented { /// /// ``` /// trait Foo { -/// fn bar(&self); +/// fn bar(&self) -> u8; /// fn baz(&self); +/// fn qux(&self) -> Result; /// } /// ``` /// /// We want to implement `Foo` on one of our types, but we also want to work on /// just `bar()` first. In order for our code to compile, we need to implement -/// `baz()`, so we can use `todo!`: +/// `baz()` and `qux()`, so we can use `todo!`: /// /// ``` /// # trait Foo { -/// # fn bar(&self); +/// # fn bar(&self) -> u8; /// # fn baz(&self); +/// # fn qux(&self) -> Result; /// # } /// struct MyStruct; /// /// impl Foo for MyStruct { -/// fn bar(&self) { -/// // implementation goes here +/// fn bar(&self) -> u8 { +/// 1 + 1 /// } /// /// fn baz(&self) { -/// // let's not worry about implementing baz() for now +/// // Let's not worry about implementing baz() for now /// todo!(); /// } +/// +/// fn qux(&self) -> Result { +/// // We can add a message to todo! to display our omission. +/// // This will display: +/// // "thread 'main' panicked at 'not yet implemented: MyStruct is not yet quxable'". +/// todo!("MyStruct is not yet quxable"); +/// } /// } /// /// fn main() { /// let s = MyStruct; /// s.bar(); /// -/// // we aren't even using baz(), so this is fine. +/// // We aren't even using baz() or qux(), so this is fine. /// } /// ``` #[macro_export] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 5ec751e5168bf..5ed82e26a0ae7 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -986,11 +986,16 @@ pub trait Tuple {} pub trait PointerLike {} /// A marker for types which can be used as types of `const` generic parameters. +/// +/// These types must have a proper equivalence relation (`Eq`) and it must be automatically +/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring +/// that all fields are also `ConstParamTy`, which implies that recursively, all fields +/// are `StructuralPartialEq`. #[lang = "const_param_ty"] #[unstable(feature = "adt_const_params", issue = "95174")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[allow(multiple_supertrait_upcastable)] -pub trait ConstParamTy: StructuralEq + StructuralPartialEq {} +pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {} /// Derive macro generating an impl of the trait `ConstParamTy`. #[rustc_builtin_macro] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 5f3d66e3773f1..98cff3493a7ea 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -4,12 +4,12 @@ use crate::ptr; /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. /// This wrapper is 0-cost. /// -/// `ManuallyDrop` is guaranteed to have the same layout as `T`, and is subject -/// to the same layout optimizations as `T`. As a consequence, it has *no effect* -/// on the assumptions that the compiler makes about its contents. For example, -/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined -/// behavior. If you need to handle uninitialized data, use [`MaybeUninit`] -/// instead. +/// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +/// `T`, and is subject to the same layout optimizations as `T`. As a consequence, +/// it has *no effect* on the assumptions that the compiler makes about its +/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] +/// is undefined behavior. If you need to handle uninitialized data, use +/// [`MaybeUninit`] instead. /// /// Note that accessing the value inside a `ManuallyDrop` is safe. /// This means that a `ManuallyDrop` whose content has been dropped must not diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index d7abc9a0e23aa..d1b1eb7624ba4 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -723,15 +723,12 @@ pub unsafe fn uninitialized() -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_diagnostic_item = "mem_swap"] pub const fn swap(x: &mut T, y: &mut T) { // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary // reinterpretation of values as (chunkable) byte arrays, and the loop in the // block optimization in `swap_slice` is hard to rewrite back // into the (unoptimized) direct swapping implementation, so we disable it. - // FIXME(eddyb) the block optimization also prevents MIR optimizations from - // understanding `mem::replace`, `Option::take`, etc. - a better overall - // solution might be to make `ptr::swap_nonoverlapping` into an intrinsic, which - // a backend can choose to implement using the block optimization, or not. #[cfg(not(any(target_arch = "spirv")))] { // For types that are larger multiples of their alignment, the simple way @@ -768,11 +765,14 @@ pub(crate) const fn swap_simple(x: &mut T, y: &mut T) { // And LLVM actually optimizes it to 3×memcpy if called with // a type larger than it's willing to keep in a register. // Having typed reads and writes in MIR here is also good as - // it lets MIRI and CTFE understand them better, including things + // it lets Miri and CTFE understand them better, including things // like enforcing type validity for them. // Importantly, read+copy_nonoverlapping+write introduces confusing // asymmetry to the behaviour where one value went through read+write // whereas the other was copied over by the intrinsic (see #94371). + // Furthermore, using only read+write here benefits limited backends + // such as SPIR-V that work on an underlying *typed* view of memory, + // and thus have trouble with Rust's untyped memory operations. // SAFETY: exclusive references are always valid to read/write, // including being aligned, and nothing here panics so it's drop-safe. @@ -930,7 +930,7 @@ pub const fn replace(dest: &mut T, src: T) -> T { /// This function is not magic; it is literally defined as /// /// ``` -/// pub fn drop(_x: T) { } +/// pub fn drop(_x: T) {} /// ``` /// /// Because `_x` is moved into the function, it is automatically dropped before diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 290f649f9acd6..f60626b00dc8a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -377,6 +377,13 @@ impl f32 { pub const MANTISSA_DIGITS: u32 = 24; /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f32` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 6; @@ -384,31 +391,62 @@ impl f32 { /// /// This is the difference between `1.0` and the next larger representable number. /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f32 = 1.19209290e-07_f32; /// Smallest finite `f32` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f32::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f32 = -3.40282347e+38_f32; /// Smallest positive normal `f32` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f32::MIN_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; /// Largest finite `f32` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS + /// [`MAX_EXP`]: f32::MAX_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f32 = 3.40282347e+38_f32; /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -125; /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 128; - /// Minimum possible normal power of 10 exponent. + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f32::MIN_POSITIVE #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -37; - /// Maximum possible power of 10 exponent. + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f32::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 38; @@ -820,7 +858,7 @@ impl f32 { /// let angle = std::f32::consts::PI; /// /// let abs_difference = (angle.to_degrees() - 180.0).abs(); - /// + /// # #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] /// assert!(abs_difference <= f32::EPSILON); /// ``` #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 7569d2cd6ca97..0a87021d8c183 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -376,6 +376,13 @@ impl f64 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MANTISSA_DIGITS: u32 = 53; /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f64` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 15; @@ -383,31 +390,62 @@ impl f64 { /// /// This is the difference between `1.0` and the next larger representable number. /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; /// Smallest finite `f64` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f64::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f64 = -1.7976931348623157e+308_f64; /// Smallest positive normal `f64` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f64::MIN_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; /// Largest finite `f64` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS + /// [`MAX_EXP`]: f64::MAX_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f64 = 1.7976931348623157e+308_f64; /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -1021; /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 1024; - /// Minimum possible normal power of 10 exponent. + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f64::MIN_POSITIVE #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -307; - /// Maximum possible power of 10 exponent. + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f64::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 308; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 1f43520e1b30a..3cbb55af3bc66 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -898,6 +898,30 @@ macro_rules! int_impl { acc.checked_mul(base) } + /// Returns the square root of the number, rounded down. + /// + /// Returns `None` if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_isqrt(self) -> Option { + if self < 0 { + None + } else { + Some((self as $UnsignedT).isqrt() as Self) + } + } + /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric /// bounds instead of overflowing. /// @@ -2061,6 +2085,36 @@ macro_rules! int_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + // I would like to implement it as + // ``` + // self.checked_isqrt().expect("argument of integer square root must be non-negative") + // ``` + // but `expect` is not yet stable as a `const fn`. + match self.checked_isqrt() { + Some(sqrt) => sqrt, + None => panic!("argument of integer square root must be non-negative"), + } + } + /// Calculates the quotient of Euclidean division of `self` by `rhs`. /// /// This computes the integer `q` such that `self = q * rhs + r`, with diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 23ca37817d4fd..a9c5312a1c02b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1259,6 +1259,10 @@ macro_rules! uint_impl { /// This function exists, so that all operations /// are accounted for in the wrapping operations. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1284,6 +1288,10 @@ macro_rules! uint_impl { /// definitions of division are equal, this /// is exactly equal to `self.wrapping_div(rhs)`. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1307,6 +1315,10 @@ macro_rules! uint_impl { /// This function exists, so that all operations /// are accounted for in the wrapping operations. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1333,6 +1345,10 @@ macro_rules! uint_impl { /// definitions of division are equal, this /// is exactly equal to `self.wrapping_rem(rhs)`. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1979,6 +1995,54 @@ macro_rules! uint_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + if self < 2 { + return self; + } + + // The algorithm is based on the one presented in + // + // which cites as source the following C code: + // . + + let mut op = self; + let mut res = 0; + let mut one = 1 << (self.ilog2() & !1); + + while one != 0 { + if op >= res + one { + op -= res + one; + res = (res >> 1) + one; + } else { + res >>= 1; + } + one >>= 2; + } + + // SAFETY: the result is positive and fits in an integer with half as many bits. + // Inform the optimizer about it. + unsafe { + intrinsics::assume(0 < res); + intrinsics::assume(res < 1 << (Self::BITS / 2)); + } + + res + } + /// Performs Euclidean division. /// /// Since, for the positive integers, all common diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 911761c6edd22..d6f2f5ca3662b 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -180,6 +180,7 @@ impl Deref for &mut T { pub trait DerefMut: Deref { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_mut_method"] fn deref_mut(&mut self) -> &mut Self::Target; } diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 21c23dabfc2c7..34dfa9e4c51fc 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -202,7 +202,7 @@ /// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] +// FIXME(effects) #[const_trait] pub trait Drop { /// Executes the destructor for this type. /// diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 67c8245f0bfe0..20f0bba4c13b6 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -72,7 +72,7 @@ use crate::marker::Tuple; )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] +// FIXME(effects) #[const_trait] pub trait Fn: FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -159,7 +159,7 @@ pub trait Fn: FnMut { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] +// FIXME(effects) #[const_trait] pub trait FnMut: FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -238,7 +238,7 @@ pub trait FnMut: FnOnce { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] +// FIXME(effects) #[const_trait] pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index cc596293ca3fe..b41600958876b 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -758,6 +758,7 @@ impl Bound<&T> { /// `RangeBounds` is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[stable(feature = "collections_range", since = "1.28.0")] +#[rustc_diagnostic_item = "RangeBounds"] pub trait RangeBounds { /// Start index bound. /// diff --git a/library/core/src/option.rs b/library/core/src/option.rs index f2909a81d4920..bdaeea666221c 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -743,8 +743,6 @@ impl Option { /// # Examples /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!( /// [Some(1234).as_slice(), None.as_slice()], /// [&[1234][..], &[][..]], @@ -755,15 +753,13 @@ impl Option { /// borrowing) [`[_]::first`](slice::first): /// /// ```rust - /// #![feature(option_as_slice)] - /// /// for i in [Some(1234_u16), None] { /// assert_eq!(i.as_ref(), i.as_slice().first()); /// } /// ``` #[inline] #[must_use] - #[unstable(feature = "option_as_slice", issue = "108545")] + #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] pub fn as_slice(&self) -> &[T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -794,8 +790,6 @@ impl Option { /// # Examples /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!( /// [Some(1234).as_mut_slice(), None.as_mut_slice()], /// [&mut [1234][..], &mut [][..]], @@ -806,8 +800,6 @@ impl Option { /// our original `Option`: /// /// ```rust - /// #![feature(option_as_slice)] - /// /// let mut x = Some(1234); /// x.as_mut_slice()[0] += 1; /// assert_eq!(x, Some(1235)); @@ -817,13 +809,11 @@ impl Option { /// is [`[_]::first_mut`](slice::first_mut): /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123)) /// ``` #[inline] #[must_use] - #[unstable(feature = "option_as_slice", issue = "108545")] + #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] pub fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -1485,7 +1475,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] pub fn or(self, optb: Option) -> Option { match self { - Some(x) => Some(x), + x @ Some(_) => x, None => optb, } } @@ -1510,7 +1500,7 @@ impl Option { F: FnOnce() -> Option, { match self { - Some(x) => Some(x), + x @ Some(_) => x, None => f(), } } @@ -1540,8 +1530,8 @@ impl Option { #[stable(feature = "option_xor", since = "1.37.0")] pub fn xor(self, optb: Option) -> Option { match (self, optb) { - (Some(a), None) => Some(a), - (None, Some(b)) => Some(b), + (a @ Some(_), None) => a, + (None, b @ Some(_)) => b, _ => None, } } diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 386f5fcbd6ab3..a00fd322b3ce7 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -47,6 +47,7 @@ pub macro panic_2015 { #[allow_internal_unstable(core_panic, const_format_args)] #[rustc_diagnostic_item = "core_panic_2021_macro"] #[rustc_macro_transparency = "semitransparent"] +#[cfg(any(bootstrap, feature = "panic_immediate_abort"))] pub macro panic_2021 { () => ( $crate::panicking::panic("explicit panic") @@ -62,6 +63,50 @@ pub macro panic_2021 { }), } +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] +#[allow_internal_unstable( + core_panic, + core_intrinsics, + const_dispatch, + const_eval_select, + const_format_args, + rustc_attrs +)] +#[rustc_diagnostic_item = "core_panic_2021_macro"] +#[rustc_macro_transparency = "semitransparent"] +#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))] +pub macro panic_2021 { + () => ({ + // Create a function so that the argument for `track_caller` + // can be moved inside if possible. + #[cold] + #[track_caller] + #[inline(never)] + const fn panic_cold_explicit() -> ! { + $crate::panicking::panic_explicit() + } + panic_cold_explicit(); + }), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + #[cold] + #[track_caller] + #[inline(never)] + #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval + #[rustc_do_not_const_check] // hooked by const-eval + const fn panic_cold_display(arg: &T) -> ! { + $crate::panicking::panic_display(arg) + } + panic_cold_display(&$arg); + }), + ($($t:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + }), +} + #[doc(hidden)] #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] #[allow_internal_unstable(core_panic)] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 281f8c1e1663c..1a32cf92ffbea 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! { panic_display(&expr); } +#[track_caller] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[rustc_const_unstable(feature = "core_panic", issue = "none")] +pub const fn panic_explicit() -> ! { + panic_display(&"explicit panic"); +} + #[inline] #[track_caller] #[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint @@ -161,8 +169,10 @@ pub fn unreachable_display(x: &T) -> ! { #[inline] #[track_caller] -#[lang = "panic_display"] // needed for const-evaluated panics #[rustc_do_not_const_check] // hooked by const-eval +#[cfg_attr(bootstrap, lang = "panic_display")] +// enforce a &&str argument in const-check and hook this by const-eval +#[cfg_attr(not(bootstrap), rustc_const_panic_str)] #[rustc_const_unstable(feature = "core_panic", issue = "none")] pub const fn panic_display(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); @@ -234,7 +244,8 @@ fn panic_in_cleanup() -> ! { #[rustc_const_unstable(feature = "core_panic", issue = "none")] pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if let Some(msg) = fmt.as_str() { - panic_str(msg); + // The panic_display function is hooked by const eval. + panic_display(&msg); } else { // SAFETY: This is only evaluated at compile time, which reliably // handles this UB (in case this branch turns out to be reachable diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 6b319b4355ce6..94c682b615ad4 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -572,7 +572,10 @@ impl Pin

{ /// // though we have previously pinned it! We have violated the pinning API contract. /// } /// ``` - /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`). + /// A value, once pinned, must remain pinned until it is dropped (unless its type implements + /// `Unpin`). Because `Pin<&mut T>` does not own the value, dropping the `Pin` will not drop + /// the value and will not end the pinning contract. So moving the value after dropping the + /// `Pin<&mut T>` is still a violation of the API contract. /// /// Similarly, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be /// aliases to the same data that are not subject to the pinning restrictions: diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index fd5fe5a04f4d9..380a21b376bde 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1142,10 +1142,9 @@ impl Copy for (T,) { /// surprising results upon inspecting the bit patterns, /// as the same calculations might produce NaNs with different bit patterns. /// -/// When the number resulting from a primitive operation (addition, -/// subtraction, multiplication, or division) on this type is not exactly -/// representable as `f32`, it is rounded according to the roundTiesToEven -/// direction defined in IEEE 754-2008. That means: +/// When a primitive operation (addition, subtraction, multiplication, or +/// division) is performed on this type, the result is rounded according to the +/// roundTiesToEven direction defined in IEEE 754-2008. That means: /// /// - The result is the representable value closest to the true value, if there /// is a unique closest representable value. @@ -1154,6 +1153,9 @@ impl Copy for (T,) { /// - If the true value's magnitude is ≥ `f32::MAX` + 2(`f32::MAX_EXP` − /// `f32::MANTISSA_DIGITS` − 1), the result is ∞ or −∞ (preserving the /// true value's sign). +/// - If the result of a sum exactly equals zero, the outcome is +0.0 unless +/// both arguments were negative, then it is -0.0. Subtraction `a - b` is +/// regarded as a sum `a + (-b)`. /// /// For more information on floating point numbers, see [Wikipedia][wikipedia]. /// diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ee69d89a4b720..9af8f1228f0b6 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,7 +607,16 @@ impl *const T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: #method.offset /// @@ -616,7 +625,7 @@ impl *const T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -646,6 +655,14 @@ impl *const T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -703,7 +720,7 @@ impl *const T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index d1286a1dea795..5039ff53d0313 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -494,6 +494,7 @@ mod mut_ptr; #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang = "drop_in_place"] #[allow(unconditional_recursion)] +#[rustc_diagnostic_item = "ptr_drop_in_place"] pub unsafe fn drop_in_place(to_drop: *mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. @@ -740,6 +741,7 @@ pub const fn from_mut(r: &mut T) -> *mut T { #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")] #[rustc_allow_const_fn_unstable(ptr_metadata)] +#[rustc_diagnostic_item = "ptr_slice_from_raw_parts"] pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { from_raw_parts(data.cast(), len) } @@ -772,6 +774,7 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")] +#[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { from_raw_parts_mut(data.cast(), len) } @@ -850,6 +853,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_diagnostic_item = "ptr_swap"] pub const unsafe fn swap(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. @@ -911,6 +915,7 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_diagnostic_item = "ptr_swap_nonoverlapping"] pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { #[allow(unused)] macro_rules! attempt_swap_as_chunks { @@ -1022,6 +1027,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be // cast to a mutable reference (valid for writes, aligned, initialized), @@ -1147,6 +1153,7 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read"] pub const unsafe fn read(src: *const T) -> T { // It would be semantically correct to implement this via `copy_nonoverlapping` // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init` @@ -1264,6 +1271,7 @@ pub const unsafe fn read(src: *const T) -> T { #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { let mut tmp = MaybeUninit::::uninit(); // SAFETY: the caller must guarantee that `src` is valid for reads. @@ -1539,6 +1547,7 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { #[inline] #[stable(feature = "volatile", since = "1.9.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read_volatile"] pub unsafe fn read_volatile(src: *const T) -> T { // SAFETY: the caller must uphold the safety contract for `volatile_load`. unsafe { @@ -1864,10 +1873,35 @@ pub(crate) const unsafe fn align_offset(p: *const T, a: usize) -> usiz /// ``` #[stable(feature = "ptr_eq", since = "1.17.0")] #[inline(always)] +#[must_use = "pointer comparison produces a value"] +#[rustc_diagnostic_item = "ptr_eq"] pub fn eq(a: *const T, b: *const T) -> bool { a == b } +/// Compares the *addresses* of the two pointers for equality, +/// ignoring any metadata in fat pointers. +/// +/// If the arguments are thin pointers of the same type, +/// then this is the same as [`eq`]. +/// +/// # Examples +/// +/// ``` +/// #![feature(ptr_addr_eq)] +/// +/// let whole: &[i32; 3] = &[1, 2, 3]; +/// let first: &i32 = &whole[0]; +/// assert!(std::ptr::addr_eq(whole, first)); +/// assert!(!std::ptr::eq::(whole, first)); +/// ``` +#[unstable(feature = "ptr_addr_eq", issue = "116324")] +#[inline(always)] +#[must_use = "pointer comparison produces a value"] +pub fn addr_eq(p: *const T, q: *const U) -> bool { + (p as *const ()) == (q as *const ()) +} + /// Hash a raw pointer. /// /// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6d623b82c1cfe..109c286929b4e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,7 +781,16 @@ impl *mut T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: pointer#method.offset-1 /// @@ -790,7 +799,7 @@ impl *mut T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -820,6 +829,14 @@ impl *mut T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -875,7 +892,7 @@ impl *mut T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d5bd54fd59ad7..5f5a10bbdf325 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -68,6 +68,7 @@ use crate::slice::{self, SliceIndex}; #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] +#[rustc_diagnostic_item = "NonNull"] pub struct NonNull { pointer: *const T, } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 6981abc9be19d..50127b27f8bfc 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1422,6 +1422,7 @@ impl Result { /// assert_eq!(Err("foo").unwrap_or_else(count), 3); /// ``` #[inline] + #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_else T>(self, op: F) -> T { match self { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index cc9313553183c..5e229bf524411 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -59,6 +59,7 @@ impl<'a, T> IntoIterator for &'a mut [T] { /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] +#[rustc_diagnostic_item = "SliceIter"] pub struct Iter<'a, T: 'a> { /// The pointer to the next element to return, or the past-the-end location /// if the iterator is empty. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0d635aced85bf..a19fcf93c4d90 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3410,7 +3410,7 @@ impl [T] { /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); /// ``` /// - /// Rotate a subslice: + /// Rotating a subslice: /// /// ``` /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 48a6eb03b5e1c..9cdf9b68afb72 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -90,6 +90,7 @@ use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")] #[must_use] +#[rustc_diagnostic_item = "slice_from_raw_parts"] pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { @@ -136,6 +137,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")] #[must_use] +#[rustc_diagnostic_item = "slice_from_raw_parts_mut"] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index cd16810c4dde7..c30f01b3c06a4 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1360,7 +1360,7 @@ impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> { } #[stable(feature = "split_inclusive", since = "1.51.0")] -impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator +impl<'a, P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>> DoubleEndedIterator for SplitInclusive<'a, P> { #[inline] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index eb0c424e2d254..899d572f0e342 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -808,7 +808,7 @@ impl str { /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); /// - /// // note the 3 here - the last character took up two bytes + /// // note the 3 here - the previous character took up two bytes /// assert_eq!(Some((3, 'e')), char_indices.next()); /// assert_eq!(Some((4, 's')), char_indices.next()); /// diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 2b37af66bd6af..16fb1dad7230f 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -624,6 +624,7 @@ pub trait FromStr: Sized { /// assert_eq!(5, x); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "from_str_method"] fn from_str(s: &str) -> Result; } diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index 3f3e19c55d4ba..ff538d55c6079 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -2,6 +2,8 @@ use core::fmt; use core::future::Future; +use core::marker::Tuple; +use core::ops::{Generator, GeneratorState}; use core::pin::Pin; use core::task::{Context, Poll}; @@ -168,10 +170,52 @@ impl From for Exclusive { } #[unstable(feature = "exclusive_wrapper", issue = "98407")] -impl Future for Exclusive { +impl FnOnce for Exclusive +where + F: FnOnce, + Args: Tuple, +{ + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + self.into_inner().call_once(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl FnMut for Exclusive +where + F: FnMut, + Args: Tuple, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + self.get_mut().call_mut(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl Future for Exclusive +where + T: Future + ?Sized, +{ type Output = T::Output; + #[inline] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.get_pin_mut().poll(cx) } } + +#[unstable(feature = "generator_trait", issue = "43122")] // also #98407 +impl Generator for Exclusive +where + G: Generator + ?Sized, +{ + type Yield = G::Yield; + type Return = G::Return; + + #[inline] + fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume(self.get_pin_mut(), arg) + } +} diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 1e8d28979e6be..6ef35d8414be5 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -910,6 +910,7 @@ impl Duration { impl Add for Duration { type Output = Duration; + #[inline] fn add(self, rhs: Duration) -> Duration { self.checked_add(rhs).expect("overflow when adding durations") } @@ -917,6 +918,7 @@ impl Add for Duration { #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl AddAssign for Duration { + #[inline] fn add_assign(&mut self, rhs: Duration) { *self = *self + rhs; } @@ -926,6 +928,7 @@ impl AddAssign for Duration { impl Sub for Duration { type Output = Duration; + #[inline] fn sub(self, rhs: Duration) -> Duration { self.checked_sub(rhs).expect("overflow when subtracting durations") } @@ -933,6 +936,7 @@ impl Sub for Duration { #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl SubAssign for Duration { + #[inline] fn sub_assign(&mut self, rhs: Duration) { *self = *self - rhs; } @@ -942,6 +946,7 @@ impl SubAssign for Duration { impl Mul for Duration { type Output = Duration; + #[inline] fn mul(self, rhs: u32) -> Duration { self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") } @@ -951,6 +956,7 @@ impl Mul for Duration { impl Mul for u32 { type Output = Duration; + #[inline] fn mul(self, rhs: Duration) -> Duration { rhs * self } @@ -958,6 +964,7 @@ impl Mul for u32 { #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl MulAssign for Duration { + #[inline] fn mul_assign(&mut self, rhs: u32) { *self = *self * rhs; } @@ -967,6 +974,7 @@ impl MulAssign for Duration { impl Div for Duration { type Output = Duration; + #[inline] fn div(self, rhs: u32) -> Duration { self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") } @@ -974,6 +982,7 @@ impl Div for Duration { #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl DivAssign for Duration { + #[inline] fn div_assign(&mut self, rhs: u32) { *self = *self / rhs; } diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 982d7853f6936..81da75d32a1c9 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -663,7 +663,7 @@ fn array_mixed_equality_nans() { #[test] fn array_into_iter_fold() { - // Strings to help MIRI catch if we double-free or something + // Strings to help Miri catch if we double-free or something let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()]; let mut s = "s".to_string(); a.into_iter().for_each(|b| s += &b); @@ -679,7 +679,7 @@ fn array_into_iter_fold() { #[test] fn array_into_iter_rfold() { - // Strings to help MIRI catch if we double-free or something + // Strings to help Miri catch if we double-free or something let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()]; let mut s = "s".to_string(); a.into_iter().rev().for_each(|b| s += &b); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 17011b845cfb5..e4003a208bc98 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -56,6 +56,7 @@ #![feature(min_specialization)] #![feature(numfmt)] #![feature(num_midpoint)] +#![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] #![feature(std_internals)] @@ -96,6 +97,7 @@ #![feature(const_option_ext)] #![feature(const_result)] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] +#![cfg_attr(test, feature(cfg_match))] #![feature(int_roundings)] #![feature(slice_group_by)] #![feature(split_array)] @@ -139,6 +141,7 @@ mod hash; mod intrinsics; mod iter; mod lazy; +#[cfg(test)] mod macros; mod manually_drop; mod mem; diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs index ff3632e3550c2..eb886def164ac 100644 --- a/library/core/tests/macros.rs +++ b/library/core/tests/macros.rs @@ -1,3 +1,25 @@ +trait Trait { + fn blah(&self); +} + +#[allow(dead_code)] +struct Struct; + +impl Trait for Struct { + cfg_match! { + cfg(feature = "blah") => { + fn blah(&self) { + unimplemented!(); + } + } + _ => { + fn blah(&self) { + unimplemented!(); + } + } + } +} + #[test] fn assert_eq_trailing_comma() { assert_eq!(1, 1,); @@ -18,3 +40,135 @@ fn assert_ne_trailing_comma() { fn matches_leading_pipe() { matches!(1, | 1 | 2 | 3); } + +#[test] +fn cfg_match_basic() { + cfg_match! { + cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }} + } + + cfg_match! { + cfg(unix) => { fn f1_() -> bool { true }} + cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }} + } + + cfg_match! { + cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }} + cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }} + } + + cfg_match! { + cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }} + _ => { fn f3_() -> i32 { 2 }} + } + + #[cfg(target_pointer_width = "64")] + assert!(f0_()); + + #[cfg(unix)] + assert!(f1_()); + + #[cfg(target_pointer_width = "32")] + assert!(!f2_()); + #[cfg(target_pointer_width = "64")] + assert!(f2_()); + + #[cfg(not(target_pointer_width = "16"))] + assert_eq!(f3_(), 2); +} + +#[test] +fn cfg_match_debug_assertions() { + cfg_match! { + cfg(debug_assertions) => { + assert!(cfg!(debug_assertions)); + assert_eq!(4, 2+2); + } + _ => { + assert!(cfg!(not(debug_assertions))); + assert_eq!(10, 5+5); + } + } +} + +#[cfg(target_pointer_width = "64")] +#[test] +fn cfg_match_no_duplication_on_64() { + cfg_match! { + cfg(windows) => { + fn foo() {} + } + cfg(unix) => { + fn foo() {} + } + cfg(target_pointer_width = "64") => { + fn foo() {} + } + } + foo(); +} + +#[test] +fn cfg_match_options() { + cfg_match! { + cfg(test) => { + use core::option::Option as Option2; + fn works1() -> Option2 { Some(1) } + } + _ => { fn works1() -> Option { None } } + } + + cfg_match! { + cfg(feature = "foo") => { fn works2() -> bool { false } } + cfg(test) => { fn works2() -> bool { true } } + _ => { fn works2() -> bool { false } } + } + + cfg_match! { + cfg(feature = "foo") => { fn works3() -> bool { false } } + _ => { fn works3() -> bool { true } } + } + + cfg_match! { + cfg(test) => { + use core::option::Option as Option3; + fn works4() -> Option3 { Some(1) } + } + } + + cfg_match! { + cfg(feature = "foo") => { fn works5() -> bool { false } } + cfg(test) => { fn works5() -> bool { true } } + } + + assert!(works1().is_some()); + assert!(works2()); + assert!(works3()); + assert!(works4().is_some()); + assert!(works5()); +} + +#[test] +fn cfg_match_two_functions() { + cfg_match! { + cfg(target_pointer_width = "64") => { + fn foo1() {} + fn bar1() {} + } + _ => { + fn foo2() {} + fn bar2() {} + } + } + + #[cfg(target_pointer_width = "64")] + { + foo1(); + bar1(); + } + #[cfg(not(target_pointer_width = "64"))] + { + foo2(); + bar2(); + } +} diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 439bbe6699781..165d9a296176e 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -290,6 +290,38 @@ macro_rules! int_module { assert_eq!(r.saturating_pow(0), 1 as $T); } + #[test] + fn test_isqrt() { + assert_eq!($T::MIN.checked_isqrt(), None); + assert_eq!((-1 as $T).checked_isqrt(), None); + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + } + + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); + } + + for n in ($T::MAX - 127)..=$T::MAX { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); + } + } + #[test] fn test_div_floor() { let a: $T = 8; diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 7d6203db0b940..955440647eb98 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -206,6 +206,35 @@ macro_rules! uint_module { assert_eq!(r.saturating_pow(2), MAX); } + #[test] + fn test_isqrt() { + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); + } + + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); + } + + for n in ($T::MAX - 255)..=$T::MAX { + let isqrt: $T = n.isqrt(); + + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); + } + } + #[test] fn test_div_floor() { assert_eq!((8 as $T).div_floor(3), 2); diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index d675696f13f1a..6e097e2caf24b 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -44,7 +44,8 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { } } else if #[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx"), - target_os = "xous" + target_os = "xous", + target_os = "uefi", ))] { unsafe fn abort() -> ! { // call std::sys::abort_internal diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index d382fec93521a..0a70c488aec91 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1337,6 +1337,13 @@ impl Literal { Literal::new(bridge::LitKind::Char, symbol, None) } + /// Byte character literal. + #[unstable(feature = "proc_macro_byte_character", issue = "115268")] + pub fn byte_character(byte: u8) -> Literal { + let string = [byte].escape_ascii().to_string(); + Literal::new(bridge::LitKind::Byte, &string, None) + } + /// Byte string literal. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn byte_string(bytes: &[u8]) -> Literal { @@ -1411,7 +1418,15 @@ impl Literal { let hashes = get_hashes_str(n); f(&["br", hashes, "\"", symbol, "\"", hashes, suffix]) } - _ => f(&[symbol, suffix]), + bridge::LitKind::CStr => f(&["c\"", symbol, "\"", suffix]), + bridge::LitKind::CStrRaw(n) => { + let hashes = get_hashes_str(n); + f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix]) + } + + bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::Err => { + f(&[symbol, suffix]) + } }) } } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index e8f642586cd7c..feb6274d0299d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -36,6 +36,10 @@ object = { version = "0.32.0", default-features = false, optional = true, featur rand = { version = "0.8.5", default-features = false, features = ["alloc"] } rand_xorshift = "0.3.0" +[build-dependencies] +# Dependency of the `backtrace` crate's build script +cc = "1.0.67" + [target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] } @@ -48,6 +52,10 @@ hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true [target.'cfg(target_os = "wasi")'.dependencies] wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } +[target.'cfg(target_os = "uefi")'.dependencies] +r-efi = { version = "4.2.0", features = ['rustc-dep-of-std']} +r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std']} + [features] backtrace = [ "gimli-symbolize", diff --git a/library/std/build.rs b/library/std/build.rs index a81c45609ea52..49354d5a58cba 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -1,5 +1,11 @@ use std::env; +// backtrace-rs requires a feature check on Android targets, so +// we need to run its build.rs as well. +#[allow(unused_extern_crates)] +#[path = "../backtrace/build.rs"] +mod backtrace_build_rs; + fn main() { println!("cargo:rerun-if-changed=build.rs"); let target = env::var("TARGET").expect("TARGET was not set"); @@ -36,8 +42,11 @@ fn main() { || target.contains("solid") || target.contains("nintendo-3ds") || target.contains("vita") + || target.contains("aix") || target.contains("nto") || target.contains("xous") + || target.contains("hurd") + || target.contains("uefi") // See src/bootstrap/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() { @@ -50,11 +59,12 @@ fn main() { // - mipsel-sony-psp // - nvptx64-nvidia-cuda // - arch=avr - // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) // - JSON targets // - Any new targets that have not been explicitly added above. println!("cargo:rustc-cfg=feature=\"restricted-std\""); } println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); println!("cargo:rustc-cfg=backtrace_in_libstd"); + + backtrace_build_rs::main(); } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 6d85b26af5fa2..6a87f6e5f2dc5 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -144,7 +144,7 @@ impl HashSet { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize) -> HashSet { - HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, Default::default()) } + HashSet::with_capacity_and_hasher(capacity, Default::default()) } } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 73cce35ac5912..c44223a2f32c2 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -184,6 +184,7 @@ pub struct DirEntry(fs_imp::DirEntry); /// ``` #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "FsOpenOptions")] pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various timestamps on a file. @@ -201,6 +202,7 @@ pub struct FileTimes(fs_imp::FileTimes); /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "FsPermissions")] pub struct Permissions(fs_imp::FilePermissions); /// A structure representing a type of file with accessors for each file type. @@ -2241,6 +2243,7 @@ pub fn canonicalize>(path: P) -> io::Result { /// ``` #[doc(alias = "mkdir")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "fs_create_dir")] pub fn create_dir>(path: P) -> io::Result<()> { DirBuilder::new().create(path.as_ref()) } diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f63142ff01fc0..5966416e32a19 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -1,14 +1,14 @@ #[cfg(test)] mod tests; -#[cfg(target_pointer_width = "64")] +#[cfg(all(target_pointer_width = "64", not(target_os = "uefi")))] mod repr_bitpacked; -#[cfg(target_pointer_width = "64")] +#[cfg(all(target_pointer_width = "64", not(target_os = "uefi")))] use repr_bitpacked::Repr; -#[cfg(not(target_pointer_width = "64"))] +#[cfg(any(not(target_pointer_width = "64"), target_os = "uefi"))] mod repr_unpacked; -#[cfg(not(target_pointer_width = "64"))] +#[cfg(any(not(target_pointer_width = "64"), target_os = "uefi"))] use repr_unpacked::Repr; use crate::error; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index eca64fb6063d5..c93bf0202523a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -5,7 +5,7 @@ //! the [`Read`] and [`Write`] traits, which provide the //! most general interface for reading and writing input and output. //! -//! # Read and Write +//! ## Read and Write //! //! Because they are traits, [`Read`] and [`Write`] are implemented by a number //! of other types, and you can implement them for your types too. As such, @@ -238,6 +238,47 @@ //! contract. The implementation of many of these functions are subject to change over //! time and may call fewer or more syscalls/library functions. //! +//! ## I/O Safety +//! +//! Rust follows an I/O safety discipline that is comparable to its memory safety discipline. This +//! means that file descriptors can be *exclusively owned*. (Here, "file descriptor" is meant to +//! subsume similar concepts that exist across a wide range of operating systems even if they might +//! use a different name, such as "handle".) An exclusively owned file descriptor is one that no +//! other code is allowed to access in any way, but the owner is allowed to access and even close +//! it any time. A type that owns its file descriptor should usually close it in its `drop` +//! function. Types like [`File`] own their file descriptor. Similarly, file descriptors +//! can be *borrowed*, granting the temporary right to perform operations on this file descriptor. +//! This indicates that the file descriptor will not be closed for the lifetime of the borrow, but +//! it does *not* imply any right to close this file descriptor, since it will likely be owned by +//! someone else. +//! +//! The platform-specific parts of the Rust standard library expose types that reflect these +//! concepts, see [`os::unix`] and [`os::windows`]. +//! +//! To uphold I/O safety, it is crucial that no code acts on file descriptors it does not own or +//! borrow, and no code closes file descriptors it does not own. In other words, a safe function +//! that takes a regular integer, treats it as a file descriptor, and acts on it, is *unsound*. +//! +//! Not upholding I/O safety and acting on a file descriptor without proof of ownership can lead to +//! misbehavior and even Undefined Behavior in code that relies on ownership of its file +//! descriptors: a closed file descriptor could be re-allocated, so the original owner of that file +//! descriptor is now working on the wrong file. Some code might even rely on fully encapsulating +//! its file descriptors with no operations being performed by any other part of the program. +//! +//! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the +//! underlying kernel object that the file descriptor references (also called "file description" on +//! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned +//! file descriptor, you cannot know whether there are any other file descriptors that reference the +//! same kernel object. However, when you create a new kernel object, you know that you are holding +//! the only reference to it. Just be careful not to lend it to anyone, since they can obtain a +//! clone and then you can no longer know what the reference count is! In that sense, [`OwnedFd`] is +//! like `Arc` and [`BorrowedFd<'a>`] is like `&'a Arc` (and similar for the Windows types). In +//! particular, given a `BorrowedFd<'a>`, you are not allowed to close the file descriptor -- just +//! like how, given a `&'a Arc`, you are not allowed to decrement the reference count and +//! potentially free the underlying object. There is no equivalent to `Box` for file descriptors in +//! the standard library (that would be a type that guarantees that the reference count is `1`), +//! however, it would be possible for a crate to define a type with those semantics. +//! //! [`File`]: crate::fs::File //! [`TcpStream`]: crate::net::TcpStream //! [`io::stdout`]: stdout @@ -245,6 +286,11 @@ //! [`?` operator]: ../../book/appendix-02-operators.html //! [`Result`]: crate::result::Result //! [`.unwrap()`]: crate::result::Result::unwrap +//! [`os::unix`]: ../os/unix/io/index.html +//! [`os::windows`]: ../os/windows/io/index.html +//! [`OwnedFd`]: ../os/fd/struct.OwnedFd.html +//! [`BorrowedFd<'a>`]: ../os/fd/struct.BorrowedFd.html +//! [`Arc`]: crate::sync::Arc #![stable(feature = "rust1", since = "1.0.0")] @@ -1190,22 +1236,22 @@ impl<'a> IoSliceMut<'a> { pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; - // Total length of all the to be removed buffers. - let mut accumulated_len = 0; + // Remaining length before reaching n. + let mut left = n; for buf in bufs.iter() { - if accumulated_len + buf.len() > n { - break; - } else { - accumulated_len += buf.len(); + if let Some(remainder) = left.checked_sub(buf.len()) { + left = remainder; remove += 1; + } else { + break; } } *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { - assert!(n == accumulated_len, "advancing io slices beyond their length"); + assert!(left == 0, "advancing io slices beyond their length"); } else { - bufs[0].advance(n - accumulated_len) + bufs[0].advance(left); } } } @@ -1333,22 +1379,25 @@ impl<'a> IoSlice<'a> { pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; - // Total length of all the to be removed buffers. - let mut accumulated_len = 0; + // Remaining length before reaching n. This prevents overflow + // that could happen if the length of slices in `bufs` were instead + // accumulated. Those slice may be aliased and, if they are large + // enough, their added length may overflow a `usize`. + let mut left = n; for buf in bufs.iter() { - if accumulated_len + buf.len() > n { - break; - } else { - accumulated_len += buf.len(); + if let Some(remainder) = left.checked_sub(buf.len()) { + left = remainder; remove += 1; + } else { + break; } } *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { - assert!(n == accumulated_len, "advancing io slices beyond their length"); + assert!(left == 0, "advancing io slices beyond their length"); } else { - bufs[0].advance(n - accumulated_len) + bufs[0].advance(left); } } } @@ -1781,6 +1830,7 @@ pub trait Write { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoSeek")] pub trait Seek { /// Seek to an offset, in bytes, in a stream. /// @@ -2844,6 +2894,7 @@ impl Iterator for Split { /// [`lines`]: BufRead::lines #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoLines")] pub struct Lines { buf: B, } diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 9098d36ee5381..05b21eeb40f71 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -611,6 +611,7 @@ static STDOUT: OnceLock>>> = OnceLo /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "io_stdout")] pub fn stdout() -> Stdout { Stdout { inner: STDOUT @@ -847,6 +848,7 @@ pub struct StderrLock<'a> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "io_stderr")] pub fn stderr() -> Stderr { // Note that unlike `stdout()` we don't use `at_exit` here to register a // destructor. Stderr is not buffered, so there's no need to run a diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5e3249655b838..02f4d5bc7ae14 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -259,7 +259,7 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] -#![cfg_attr(windows, feature(round_char_boundary))] +#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] // // Language features: @@ -270,6 +270,7 @@ #![feature(allow_internal_unstable)] #![feature(c_unwind)] #![feature(cfg_target_thread_local)] +#![feature(cfi_encoding)] #![feature(concat_idents)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] @@ -292,6 +293,7 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(rustc_attrs)] @@ -665,6 +667,9 @@ pub use core::{ )] pub use core::concat_bytes; +#[unstable(feature = "cfg_match", issue = "115585")] +pub use core::cfg_match; + #[stable(feature = "core_primitive", since = "1.43.0")] pub use core::primitive; diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 227e418b70992..60347a11da9c5 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -99,6 +99,16 @@ impl UdpSocket { /// /// let socket = UdpSocket::bind("127.0.0.1:0").unwrap(); /// ``` + /// + /// Note that `bind` declares the scope of your network connection. + /// You can only receive datagrams from and send datagrams to + /// participants in that view of the network. + /// For instance, binding to a loopback address as in the example + /// above will prevent you from sending datagrams to another device + /// in your local network. + /// + /// In order to limit your view of the network the least, `bind` to + /// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`]. #[stable(feature = "rust1", since = "1.0.0")] pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) @@ -157,7 +167,9 @@ impl UdpSocket { } /// Sends data on the socket to the given address. On success, returns the - /// number of bytes written. + /// number of bytes written. Note that the operating system may refuse + /// buffers larger than 65507. However, partial writes are not possible + /// until buffer sizes above `i32::MAX`. /// /// Address type can be any implementor of [`ToSocketAddrs`] trait. See its /// documentation for concrete examples. @@ -652,12 +664,19 @@ impl UdpSocket { /// function of a UDP socket is not a useful thing to do: The OS will be /// unable to determine whether something is listening on the remote /// address without the application sending data. + /// + /// If your first `connect` is to a loopback address, subsequent + /// `connect`s to non-loopback addresses might fail, depending + /// on the platform. #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn connect(&self, addr: A) -> io::Result<()> { super::each_addr(addr, |addr| self.0.connect(addr)) } /// Sends data on the socket to the remote address to which it is connected. + /// On success, returns the number of bytes written. Note that the operating + /// system may refuse buffers larger than 65507. However, partial writes are + /// not possible until buffer sizes above `i32::MAX`. /// /// [`UdpSocket::connect`] will connect this socket to a remote address. This /// method will fail if the socket is not connected. diff --git a/library/std/src/os/aix/fs.rs b/library/std/src/os/aix/fs.rs new file mode 100644 index 0000000000000..ac9dd45f05426 --- /dev/null +++ b/library/std/src/os/aix/fs.rs @@ -0,0 +1,348 @@ +//! AIX specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs + +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + /// Returns the last access time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + /// Returns the last access time of the file, in nanoseconds since [`st_atime`]. + /// + /// [`st_atime`]: Self::st_atime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + /// Returns the last modification time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`]. + /// + /// [`st_mtime`]: Self::st_mtime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + /// Returns the last status change time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`]. + /// + /// [`st_ctime`]: Self::st_ctime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + /// Returns the "preferred" block size for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::aix::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime.tv_sec as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime.tv_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime.tv_sec as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime.tv_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime.tv_sec as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime.tv_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/aix/mod.rs b/library/std/src/os/aix/mod.rs new file mode 100644 index 0000000000000..7f86a3c77f210 --- /dev/null +++ b/library/std/src/os/aix/mod.rs @@ -0,0 +1,6 @@ +//! AIX specific definitions. + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; diff --git a/library/std/src/os/aix/raw.rs b/library/std/src/os/aix/raw.rs new file mode 100644 index 0000000000000..b4c8dc72cfe5b --- /dev/null +++ b/library/std/src/os/aix/raw.rs @@ -0,0 +1,9 @@ +//! AIX specific raw type definitions. + +#![stable(feature = "raw_ext", since = "1.1.0")] + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub use libc::pthread_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use libc::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, stat, time_t}; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 2180d2974d5ae..81106d6c62c3f 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -15,8 +15,9 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// A borrowed file descriptor. /// -/// This has a lifetime parameter to tie it to the lifetime of something that -/// owns the file descriptor. +/// This has a lifetime parameter to tie it to the lifetime of something that owns the file +/// descriptor. For the duration of that lifetime, it is guaranteed that nobody will close the file +/// descriptor. /// /// This uses `repr(transparent)` and has the representation of a host file /// descriptor, so it can be used in FFI in places where a file descriptor is @@ -42,7 +43,8 @@ pub struct BorrowedFd<'fd> { /// An owned file descriptor. /// -/// This closes the file descriptor on drop. +/// This closes the file descriptor on drop. It is guaranteed that nobody else will close the file +/// descriptor. /// /// This uses `repr(transparent)` and has the representation of a host file /// descriptor, so it can be used in FFI in places where a file descriptor is @@ -155,7 +157,9 @@ impl FromRawFd for OwnedFd { /// # Safety /// /// The resource pointed to by `fd` must be open and suitable for assuming - /// ownership. The resource must not require any cleanup other than `close`. + /// [ownership][io-safety]. The resource must not require any cleanup other than `close`. + /// + /// [io-safety]: io#io-safety #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { assert_ne!(fd, u32::MAX as RawFd); diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 592e072ad908a..ef896ea95c9c9 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -84,7 +84,10 @@ pub trait FromRawFd { /// /// # Safety /// - /// The `fd` passed in must be a valid and open file descriptor. + /// The `fd` passed in must be an [owned file descriptor][io-safety]; + /// in particular, it must be open. + /// + /// [io-safety]: io#io-safety /// /// # Example /// diff --git a/library/std/src/os/fortanix_sgx/io.rs b/library/std/src/os/fortanix_sgx/io.rs index 7223ade68158f..7e57435b65ccd 100644 --- a/library/std/src/os/fortanix_sgx/io.rs +++ b/library/std/src/os/fortanix_sgx/io.rs @@ -31,15 +31,22 @@ pub trait FromRawFd { /// Constructs a new instance of `Self` from the given raw file /// descriptor and metadata. /// - /// This function **consumes ownership** of the specified file - /// descriptor. The returned object will take responsibility for closing - /// it when the object goes out of scope. + /// This function is typically used to **consume ownership** of the + /// specified file descriptor. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. + /// However, consuming ownership is not strictly required. Use a + /// [`From::from`] implementation for an API which strictly + /// consumes ownership. + /// + /// # Safety + /// + /// The `fd` passed in must be an [owned file descriptor][io-safety]; + /// in particular, it must be open. + // FIXME: say something about `metadata`. + /// + /// [io-safety]: io#io-safety #[unstable(feature = "sgx_platform", issue = "56975")] unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> Self; } diff --git a/library/std/src/os/hurd/fs.rs b/library/std/src/os/hurd/fs.rs new file mode 100644 index 0000000000000..00ff1560f31d9 --- /dev/null +++ b/library/std/src/os/hurd/fs.rs @@ -0,0 +1,348 @@ +//! Hurd-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs + +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + /// Returns the last access time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + /// Returns the last access time of the file, in nanoseconds since [`st_atime`]. + /// + /// [`st_atime`]: Self::st_atime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + /// Returns the last modification time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`]. + /// + /// [`st_mtime`]: Self::st_mtime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + /// Returns the last status change time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`]. + /// + /// [`st_ctime`]: Self::st_ctime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + /// Returns the "preferred" block size for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::hurd::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_fsid as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_sec as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_sec as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_sec as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/hurd/mod.rs b/library/std/src/os/hurd/mod.rs new file mode 100644 index 0000000000000..aee86c7f61655 --- /dev/null +++ b/library/std/src/os/hurd/mod.rs @@ -0,0 +1,6 @@ +//! Hurd-specific definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; diff --git a/library/std/src/os/hurd/raw.rs b/library/std/src/os/hurd/raw.rs new file mode 100644 index 0000000000000..fa266663528ca --- /dev/null +++ b/library/std/src/os/hurd/raw.rs @@ -0,0 +1,33 @@ +//! Hurd-specific raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +use crate::os::raw::{c_long, c_uint, c_ulong}; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = c_long; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = c_ulong; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = c_uint; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = c_ulong; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = c_long; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = c_long; diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index de6d784c65b1d..6e11b92b618a3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -97,6 +97,8 @@ pub mod wasi; pub mod windows; // Others. +#[cfg(target_os = "aix")] +pub mod aix; #[cfg(target_os = "android")] pub mod android; #[cfg(target_os = "dragonfly")] @@ -117,6 +119,8 @@ pub mod haiku; pub mod hermit; #[cfg(target_os = "horizon")] pub mod horizon; +#[cfg(target_os = "hurd")] +pub mod hurd; #[cfg(target_os = "illumos")] pub mod illumos; #[cfg(target_os = "ios")] @@ -140,6 +144,8 @@ pub mod solid; #[cfg(target_os = "tvos")] #[path = "ios/mod.rs"] pub(crate) mod tvos; +#[cfg(target_os = "uefi")] +pub mod uefi; #[cfg(target_os = "vita")] pub mod vita; #[cfg(target_os = "vxworks")] diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 33cc5a015b5dc..f82034663d4e6 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -27,15 +27,21 @@ pub trait FromRawFd { /// Constructs a new instance of `Self` from the given raw file /// descriptor. /// - /// This function **consumes ownership** of the specified file - /// descriptor. The returned object will take responsibility for closing - /// it when the object goes out of scope. + /// This function is typically used to **consume ownership** of the + /// specified file descriptor. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. + /// However, consuming ownership is not strictly required. Use a + /// [`From::from`] implementation for an API which strictly + /// consumes ownership. + /// + /// # Safety + /// + /// The `fd` passed in must be an [owned file descriptor][io-safety]; + /// in particular, it must be open. + /// + /// [io-safety]: io#io-safety unsafe fn from_raw_fd(fd: RawFd) -> Self; } diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs new file mode 100644 index 0000000000000..5d082e7c11388 --- /dev/null +++ b/library/std/src/os/uefi/env.rs @@ -0,0 +1,92 @@ +//! UEFI-specific extensions to the primitives in `std::env` module + +#![unstable(feature = "uefi_std", issue = "100499")] + +use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::{ffi::c_void, ptr::NonNull}; + +static SYSTEM_TABLE: AtomicPtr = AtomicPtr::new(crate::ptr::null_mut()); +static IMAGE_HANDLE: AtomicPtr = AtomicPtr::new(crate::ptr::null_mut()); +// Flag to check if BootServices are still valid. +// Start with assuming that they are not available +static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false); + +/// Initializes the global System Table and Image Handle pointers. +/// +/// The standard library requires access to the UEFI System Table and the Application Image Handle +/// to operate. Those are provided to UEFI Applications via their application entry point. By +/// calling `init_globals()`, those pointers are retained by the standard library for future use. +/// Thus this function must be called before any of the standard library services are used. +/// +/// The pointers are never exposed to any entity outside of this application and it is guaranteed +/// that, once the application exited, these pointers are never dereferenced again. +/// +/// Callers are required to ensure the pointers are valid for the entire lifetime of this +/// application. In particular, UEFI Boot Services must not be exited while an application with the +/// standard library is loaded. +/// +/// # SAFETY +/// Calling this function more than once will panic +pub(crate) unsafe fn init_globals(handle: NonNull, system_table: NonNull) { + IMAGE_HANDLE + .compare_exchange( + crate::ptr::null_mut(), + handle.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .unwrap(); + SYSTEM_TABLE + .compare_exchange( + crate::ptr::null_mut(), + system_table.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .unwrap(); + BOOT_SERVICES_FLAG.store(true, Ordering::Release) +} + +/// Get the SystemTable Pointer. +/// If you want to use `BootServices` then please use [`boot_services`] as it performs some +/// additional checks. +/// +/// Note: This function panics if the System Table or Image Handle is not initialized +pub fn system_table() -> NonNull { + try_system_table().unwrap() +} + +/// Get the ImageHandle Pointer. +/// +/// Note: This function panics if the System Table or Image Handle is not initialized +pub fn image_handle() -> NonNull { + try_image_handle().unwrap() +} + +/// Get the BootServices Pointer. +/// This function also checks if `ExitBootServices` has already been called. +pub fn boot_services() -> Option> { + if BOOT_SERVICES_FLAG.load(Ordering::Acquire) { + let system_table: NonNull = try_system_table()?.cast(); + let boot_services = unsafe { (*system_table.as_ptr()).boot_services }; + NonNull::new(boot_services).map(|x| x.cast()) + } else { + None + } +} + +/// Get the SystemTable Pointer. +/// This function is mostly intended for places where panic is not an option +pub(crate) fn try_system_table() -> Option> { + NonNull::new(SYSTEM_TABLE.load(Ordering::Acquire)) +} + +/// Get the SystemHandle Pointer. +/// This function is mostly intended for places where panicking is not an option +pub(crate) fn try_image_handle() -> Option> { + NonNull::new(IMAGE_HANDLE.load(Ordering::Acquire)) +} + +pub(crate) fn disable_boot_services() { + BOOT_SERVICES_FLAG.store(false, Ordering::Release) +} diff --git a/library/std/src/os/uefi/mod.rs b/library/std/src/os/uefi/mod.rs new file mode 100644 index 0000000000000..8ef05eee1f4e7 --- /dev/null +++ b/library/std/src/os/uefi/mod.rs @@ -0,0 +1,8 @@ +//! Platform-specific extensions to `std` for UEFI. + +#![unstable(feature = "uefi_std", issue = "100499")] +#![doc(cfg(target_os = "uefi"))] + +pub mod env; +#[path = "../windows/ffi.rs"] +pub mod ffi; diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 25b5dbff14f30..827278f8b2605 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -6,7 +6,8 @@ //! //! This module provides three types for representing file descriptors, //! with different ownership properties: raw, borrowed, and owned, which are -//! analogous to types used for representing pointers: +//! analogous to types used for representing pointers. These types reflect concepts of [I/O +//! safety][io-safety] on Unix. //! //! | Type | Analogous to | //! | ------------------ | ------------ | @@ -17,8 +18,8 @@ //! Like raw pointers, `RawFd` values are primitive values. And in new code, //! they should be considered unsafe to do I/O on (analogous to dereferencing //! them). Rust did not always provide this guidance, so existing code in the -//! Rust ecosystem often doesn't mark `RawFd` usage as unsafe. Once the -//! `io_safety` feature is stable, libraries will be encouraged to migrate, +//! Rust ecosystem often doesn't mark `RawFd` usage as unsafe. +//! Libraries are encouraged to migrate, //! either by adding `unsafe` to APIs that dereference `RawFd` values, or by //! using to `BorrowedFd` or `OwnedFd` instead. //! @@ -54,6 +55,8 @@ //! Like boxes, `OwnedFd` values conceptually own the resource they point to, //! and free (close) it when they are dropped. //! +//! See the [`io` module docs][io-safety] for a general explanation of I/O safety. +//! //! ## `/proc/self/mem` and similar OS features //! //! Some platforms have special files, such as `/proc/self/mem`, which @@ -65,15 +68,16 @@ //! to be opened and read from or written must be `unsafe`. Rust's safety guarantees //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an -//! external entity, along with debugging interfaces, and people with physical access to -//! the hardware. This is true even in cases where the program is controlling -//! the external entity. +//! external entity, along with `/proc/self/fd/*`, debugging interfaces, and people with physical +//! access to the hardware. This is true even in cases where the program is controlling the external +//! entity. //! //! If you desire to comprehensively prevent programs from reaching out and //! causing external entities to reach back in and violate memory safety, it's //! necessary to use *sandboxing*, which is outside the scope of `std`. //! //! [`BorrowedFd<'a>`]: crate::os::unix::io::BorrowedFd +//! [io-safety]: crate::io#io-safety #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 401ec1e7a0130..5ba8719e6ffeb 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -37,6 +37,8 @@ use crate::os::linux as platform; #[cfg(not(doc))] mod platform { + #[cfg(target_os = "aix")] + pub use crate::os::aix::*; #[cfg(target_os = "android")] pub use crate::os::android::*; #[cfg(target_os = "dragonfly")] @@ -53,6 +55,8 @@ mod platform { pub use crate::os::haiku::*; #[cfg(target_os = "horizon")] pub use crate::os::horizon::*; + #[cfg(target_os = "hurd")] + pub use crate::os::hurd::*; #[cfg(target_os = "illumos")] pub use crate::os::illumos::*; #[cfg(target_os = "ios")] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 2b40b672d9f0a..5d9f7430ca2cb 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -434,6 +434,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStdin` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdin { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStdin { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStdin::from_inner(pipe) + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsFd for crate::process::ChildStdout { #[inline] @@ -450,6 +464,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStdout` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdout { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStdout { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStdout::from_inner(pipe) + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsFd for crate::process::ChildStderr { #[inline] @@ -466,6 +494,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStderr` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStderr { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStderr { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStderr::from_inner(pipe) + } +} + /// Returns the OS-assigned process identifier associated with this process's parent. #[must_use] #[stable(feature = "unix_ppid", since = "1.27.0")] diff --git a/library/std/src/os/windows/io/mod.rs b/library/std/src/os/windows/io/mod.rs index e2a401fb6962b..3d3ae38788639 100644 --- a/library/std/src/os/windows/io/mod.rs +++ b/library/std/src/os/windows/io/mod.rs @@ -6,7 +6,8 @@ //! //! This module provides three types for representing raw handles and sockets //! with different ownership properties: raw, borrowed, and owned, which are -//! analogous to types used for representing pointers: +//! analogous to types used for representing pointers. These types reflect concepts of [I/O +//! safety][io-safety] on Windows. //! //! | Type | Analogous to | //! | ---------------------- | ------------ | @@ -23,8 +24,8 @@ //! And in new code, they should be considered unsafe to do I/O on (analogous //! to dereferencing them). Rust did not always provide this guidance, so //! existing code in the Rust ecosystem often doesn't mark `RawHandle` and -//! `RawSocket` usage as unsafe. Once the `io_safety` feature is stable, -//! libraries will be encouraged to migrate, either by adding `unsafe` to APIs +//! `RawSocket` usage as unsafe. +//! Libraries are encouraged to migrate, either by adding `unsafe` to APIs //! that dereference `RawHandle` and `RawSocket` values, or by using to //! `BorrowedHandle`, `BorrowedSocket`, `OwnedHandle`, or `OwnedSocket`. //! @@ -45,8 +46,11 @@ //! Like boxes, `OwnedHandle` and `OwnedSocket` values conceptually own the //! resource they point to, and free (close) it when they are dropped. //! +//! See the [`io` module docs][io-safety] for a general explanation of I/O safety. +//! //! [`BorrowedHandle<'a>`]: crate::os::windows::io::BorrowedHandle //! [`BorrowedSocket<'a>`]: crate::os::windows::io::BorrowedSocket +//! [io-safety]: crate::io#io-safety #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 1759e2e7f3f91..770583a9ce3e0 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -62,7 +62,7 @@ pub trait FromRawHandle { /// # Safety /// /// The `handle` passed in must: - /// - be a valid an open handle, + /// - be an [owned handle][io-safety]; in particular, it must be open. /// - be a handle for a resource that may be freed via [`CloseHandle`] /// (as opposed to `RegCloseKey` or other close functions). /// @@ -71,6 +71,7 @@ pub trait FromRawHandle { /// /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 + /// [io-safety]: io#io-safety #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_handle(handle: RawHandle) -> Self; } @@ -207,10 +208,11 @@ pub trait FromRawSocket { /// # Safety /// /// The `socket` passed in must: - /// - be a valid an open socket, + /// - be an [owned socket][io-safety]; in particular, it must be open. /// - be a socket that may be freed via [`closesocket`]. /// /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket + /// [io-safety]: io#io-safety #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_socket(sock: RawSocket) -> Self; } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 6359835cad5d9..c80b9e28499bc 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -116,7 +116,7 @@ impl BorrowedSocket<'_> { let mut info = unsafe { mem::zeroed::() }; let result = unsafe { sys::c::WSADuplicateSocketW( - self.as_raw_socket(), + self.as_raw_socket() as sys::c::SOCKET, sys::c::GetCurrentProcessId(), &mut info, ) @@ -134,7 +134,7 @@ impl BorrowedSocket<'_> { }; if socket != sys::c::INVALID_SOCKET { - unsafe { Ok(OwnedSocket::from_raw_socket(socket)) } + unsafe { Ok(OwnedSocket::from_raw_socket(socket as RawSocket)) } } else { let error = unsafe { sys::c::WSAGetLastError() }; @@ -158,7 +158,7 @@ impl BorrowedSocket<'_> { } unsafe { - let socket = OwnedSocket::from_raw_socket(socket); + let socket = OwnedSocket::from_raw_socket(socket as RawSocket); socket.set_no_inherit()?; Ok(socket) } @@ -211,7 +211,7 @@ impl Drop for OwnedSocket { #[inline] fn drop(&mut self) { unsafe { - let _ = sys::c::closesocket(self.socket); + let _ = sys::c::closesocket(self.socket as sys::c::SOCKET); } } } diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 5d87216ff1b4c..94173825c4af5 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -106,6 +106,45 @@ impl IntoRawHandle for process::ChildStderr { } } +/// Create a `ChildStdin` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdin { + fn from(handle: OwnedHandle) -> process::ChildStdin { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStdin::from_inner(pipe) + } +} + +/// Create a `ChildStdout` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdout { + fn from(handle: OwnedHandle) -> process::ChildStdout { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStdout::from_inner(pipe) + } +} + +/// Create a `ChildStderr` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStderr { + fn from(handle: OwnedHandle) -> process::ChildStderr { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStderr::from_inner(pipe) + } +} + /// Windows-specific extensions to [`process::ExitStatus`]. /// /// This trait is sealed: it cannot be implemented outside the standard library. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 5df1105e264ea..e148635f5819b 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -12,9 +12,9 @@ //! use std::process::Command; //! //! let output = Command::new("echo") -//! .arg("Hello world") -//! .output() -//! .expect("Failed to execute command"); +//! .arg("Hello world") +//! .output() +//! .expect("Failed to execute command"); //! //! assert_eq!(b"Hello world\n", output.stdout.as_slice()); //! ``` @@ -154,12 +154,11 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// use std::process::Command; /// /// let mut child = Command::new("/bin/cat") -/// .arg("file.txt") -/// .spawn() -/// .expect("failed to execute child"); +/// .arg("file.txt") +/// .spawn() +/// .expect("failed to execute child"); /// -/// let ecode = child.wait() -/// .expect("failed to wait on child"); +/// let ecode = child.wait().expect("failed to wait on child"); /// /// assert!(ecode.success()); /// ``` @@ -481,15 +480,15 @@ impl fmt::Debug for ChildStderr { /// /// let output = if cfg!(target_os = "windows") { /// Command::new("cmd") -/// .args(["/C", "echo hello"]) -/// .output() -/// .expect("failed to execute process") +/// .args(["/C", "echo hello"]) +/// .output() +/// .expect("failed to execute process") /// } else { /// Command::new("sh") -/// .arg("-c") -/// .arg("echo hello") -/// .output() -/// .expect("failed to execute process") +/// .arg("-c") +/// .arg("echo hello") +/// .output() +/// .expect("failed to execute process") /// }; /// /// let hello = output.stdout; @@ -502,8 +501,7 @@ impl fmt::Debug for ChildStderr { /// use std::process::Command; /// /// let mut echo_hello = Command::new("sh"); -/// echo_hello.arg("-c") -/// .arg("echo hello"); +/// echo_hello.arg("-c").arg("echo hello"); /// let hello_1 = echo_hello.output().expect("failed to execute process"); /// let hello_2 = echo_hello.output().expect("failed to execute process"); /// ``` @@ -528,6 +526,7 @@ impl fmt::Debug for ChildStderr { /// list_dir.status().expect("process failed to execute"); /// ``` #[stable(feature = "process", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Command")] pub struct Command { inner: imp::Command, } @@ -576,8 +575,8 @@ impl Command { /// use std::process::Command; /// /// Command::new("sh") - /// .spawn() - /// .expect("sh command failed to start"); + /// .spawn() + /// .expect("sh command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn new>(program: S) -> Command { @@ -609,7 +608,7 @@ impl Command { /// /// Note that the argument is not passed through a shell, but given /// literally to the program. This means that shell syntax like quotes, - /// escaped characters, word splitting, glob patterns, substitution, etc. + /// escaped characters, word splitting, glob patterns, variable substitution, etc. /// have no effect. /// /// # Examples @@ -620,10 +619,10 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .arg("-l") - /// .arg("-a") - /// .spawn() - /// .expect("ls command failed to start"); + /// .arg("-l") + /// .arg("-a") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn arg>(&mut self, arg: S) -> &mut Command { @@ -639,7 +638,7 @@ impl Command { /// /// Note that the arguments are not passed through a shell, but given /// literally to the program. This means that shell syntax like quotes, - /// escaped characters, word splitting, glob patterns, substitution, etc. + /// escaped characters, word splitting, glob patterns, variable substitution, etc. /// have no effect. /// /// # Examples @@ -650,9 +649,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .args(["-l", "-a"]) - /// .spawn() - /// .expect("ls command failed to start"); + /// .args(["-l", "-a"]) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn args(&mut self, args: I) -> &mut Command @@ -688,9 +687,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env("PATH", "/bin") - /// .spawn() - /// .expect("ls command failed to start"); + /// .env("PATH", "/bin") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env(&mut self, key: K, val: V) -> &mut Command @@ -731,12 +730,12 @@ impl Command { /// ).collect(); /// /// Command::new("printenv") - /// .stdin(Stdio::null()) - /// .stdout(Stdio::inherit()) - /// .env_clear() - /// .envs(&filtered_env) - /// .spawn() - /// .expect("printenv failed to start"); + /// .stdin(Stdio::null()) + /// .stdout(Stdio::inherit()) + /// .env_clear() + /// .envs(&filtered_env) + /// .spawn() + /// .expect("printenv failed to start"); /// ``` #[stable(feature = "command_envs", since = "1.19.0")] pub fn envs(&mut self, vars: I) -> &mut Command @@ -772,9 +771,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env_remove("PATH") - /// .spawn() - /// .expect("ls command failed to start"); + /// .env_remove("PATH") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_remove>(&mut self, key: K) -> &mut Command { @@ -789,7 +788,7 @@ impl Command { /// or [`Command::envs`]. In addition, it will prevent the spawned child process from inheriting /// any environment variable from its parent process. /// - /// After calling [`Command::env_remove`], the iterator from [`Command::get_envs`] will be + /// After calling [`Command::env_clear`], the iterator from [`Command::get_envs`] will be /// empty. /// /// You can use [`Command::env_remove`] to clear a single mapping. @@ -802,9 +801,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env_clear() - /// .spawn() - /// .expect("ls command failed to start"); + /// .env_clear() + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_clear(&mut self) -> &mut Command { @@ -830,9 +829,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .current_dir("/bin") - /// .spawn() - /// .expect("ls command failed to start"); + /// .current_dir("/bin") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` /// /// [`canonicalize`]: crate::fs::canonicalize @@ -861,9 +860,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stdin(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stdin(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stdin>(&mut self, cfg: T) -> &mut Command { @@ -890,9 +889,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stdout(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stdout(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stdout>(&mut self, cfg: T) -> &mut Command { @@ -919,9 +918,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stderr(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stderr(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stderr>(&mut self, cfg: T) -> &mut Command { @@ -941,8 +940,8 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .spawn() - /// .expect("ls command failed to start"); + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn spawn(&mut self) -> io::Result { @@ -963,9 +962,9 @@ impl Command { /// use std::process::Command; /// use std::io::{self, Write}; /// let output = Command::new("/bin/cat") - /// .arg("file.txt") - /// .output() - /// .expect("failed to execute process"); + /// .arg("file.txt") + /// .output() + /// .expect("failed to execute process"); /// /// println!("status: {}", output.status); /// io::stdout().write_all(&output.stdout).unwrap(); @@ -990,9 +989,9 @@ impl Command { /// use std::process::Command; /// /// let status = Command::new("/bin/cat") - /// .arg("file.txt") - /// .status() - /// .expect("failed to execute process"); + /// .arg("file.txt") + /// .status() + /// .expect("failed to execute process"); /// /// println!("process finished with: {status}"); /// @@ -1618,9 +1617,9 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("ls") - /// .arg("/dev/nonexistent") - /// .status() - /// .expect("ls could not be executed"); + /// .arg("/dev/nonexistent") + /// .status() + /// .expect("ls could not be executed"); /// /// println!("ls: {status}"); /// status.exit_ok().expect_err("/dev/nonexistent could be listed!"); @@ -1640,9 +1639,9 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("mkdir") - /// .arg("projects") - /// .status() - /// .expect("failed to execute mkdir"); + /// .arg("projects") + /// .status() + /// .expect("failed to execute mkdir"); /// /// if status.success() { /// println!("'projects/' directory created"); @@ -1673,13 +1672,13 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("mkdir") - /// .arg("projects") - /// .status() - /// .expect("failed to execute mkdir"); + /// .arg("projects") + /// .status() + /// .expect("failed to execute mkdir"); /// /// match status.code() { /// Some(code) => println!("Exited with status code: {code}"), - /// None => println!("Process terminated by signal") + /// None => println!("Process terminated by signal") /// } /// ``` #[must_use] @@ -1809,9 +1808,9 @@ impl ExitStatusError { } #[unstable(feature = "exit_status_error", issue = "84908")] -impl Into for ExitStatusError { - fn into(self) -> ExitStatus { - ExitStatus(self.0.into()) +impl From for ExitStatus { + fn from(error: ExitStatusError) -> Self { + Self(error.0.into()) } } @@ -2198,6 +2197,7 @@ impl Child { /// process::exit(0x0100); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")] pub fn exit(code: i32) -> ! { crate::rt::cleanup(); crate::sys::os::exit(code) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 0063623728821..07d4de5c1a26e 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -537,7 +537,7 @@ fn env_empty() { #[test] #[cfg(not(windows))] #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] -fn main() { +fn debug_print() { const PIDFD: &'static str = if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" }; @@ -623,6 +623,51 @@ fn main() { cwd: Some( "/some/path", ), +{PIDFD}}}"# + ) + ); + + let mut command_with_removed_env = Command::new("boring-name"); + command_with_removed_env.env_remove("FOO").env_remove("BAR"); + assert_eq!(format!("{command_with_removed_env:?}"), r#"env -u BAR -u FOO "boring-name""#); + assert_eq!( + format!("{command_with_removed_env:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: false, + vars: {{ + "BAR": None, + "FOO": None, + }}, + }}, +{PIDFD}}}"# + ) + ); + + let mut command_with_cleared_env = Command::new("boring-name"); + command_with_cleared_env.env_clear().env("BAR", "val").env_remove("FOO"); + assert_eq!(format!("{command_with_cleared_env:?}"), r#"env -i BAR="val" "boring-name""#); + assert_eq!( + format!("{command_with_cleared_env:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: true, + vars: {{ + "BAR": Some( + "val", + ), + }}, + }}, {PIDFD}}}"# ) ); diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 8c46080e43b38..2bb4f3f9e0383 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -125,7 +125,7 @@ impl Once { /// /// # Panics /// - /// The closure `f` will only be executed once if this is called + /// The closure `f` will only be executed once even if this is called /// concurrently amongst many threads. If that closure panics, however, then /// it will *poison* this [`Once`] instance, causing all future invocations of /// `call_once` to also panic. diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 26aaa2414c979..ac7c800ff6f8c 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -380,7 +380,7 @@ impl RwLock { /// /// If the lock is poisoned, it will remain poisoned until this function is called. This allows /// recovering from a poisoned state and marking that it has recovered. For example, if the - /// value is overwritten by a known-good value, then the mutex can be marked as un-poisoned. Or + /// value is overwritten by a known-good value, then the lock can be marked as un-poisoned. Or /// possibly, the value could be inspected to determine if it is in a consistent state, and if /// so the poison is removed. /// @@ -397,7 +397,7 @@ impl RwLock { /// /// let _ = thread::spawn(move || { /// let _lock = c_lock.write().unwrap(); - /// panic!(); // the mutex gets poisoned + /// panic!(); // the lock gets poisoned /// }).join(); /// /// assert_eq!(lock.is_poisoned(), true); diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index 975509bd412b0..8b2c839f837d4 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -6,7 +6,7 @@ // "static" is for single-threaded platforms where a global static is sufficient. cfg_if::cfg_if! { - if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { + if #[cfg(any(all(target_family = "wasm", not(target_feature = "atomics")), target_os = "uefi"))] { #[doc(hidden)] mod static_local; #[doc(hidden)] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 457eb782ccc66..159ffe7ac9635 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -47,6 +47,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "xous")] { mod xous; pub use self::xous::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use self::uefi::*; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use self::sgx::*; @@ -114,4 +117,5 @@ pub fn log_wrapper f64>(n: f64, log_fn: F) -> f64 { log_fn(n) } +#[cfg(not(target_os = "uefi"))] pub type RawOsError = i32; diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index e477a0cd7ab81..559d2c7db4717 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -95,7 +95,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 cfg_if::cfg_if! { if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] { // ARM EHABI personality routine. - // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf + // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf // // iOS uses the default routine instead since it uses SjLj unwinding. #[lang = "eh_personality"] diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 01505e94487b2..817c33b660370 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -3,6 +3,8 @@ use crate::arch::asm; use crate::cell::UnsafeCell; use crate::cmp; +use crate::convert::TryInto; +use crate::intrinsics; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; use crate::ptr::{self, NonNull}; @@ -306,20 +308,35 @@ where } } -// Split a memory region ptr..ptr + len into three parts: -// +--------+ -// | small0 | Chunk smaller than 8 bytes -// +--------+ -// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes -// +--------+ -// | small1 | Chunk smaller than 8 bytes -// +--------+ -fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) { - let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 }; - let small1_size = (len - small0_size) % 8; - let big_size = len - small0_size - small1_size; - - (small0_size, big_size, small1_size) +/// Divide the slice `(ptr, len)` into three parts, where the middle part is +/// aligned to `u64`. +/// +/// The return values `(prefix_len, mid_len, suffix_len)` add back up to `len`. +/// The return values are such that the memory region `(ptr + prefix_len, +/// mid_len)` is the largest possible region where `ptr + prefix_len` is aligned +/// to `u64` and `mid_len` is a multiple of the byte size of `u64`. This means +/// that `prefix_len` and `suffix_len` are guaranteed to be less than the byte +/// size of `u64`, and that `(ptr, prefix_len)` and `(ptr + prefix_len + +/// mid_len, suffix_len)` don't straddle an alignment boundary. +// Standard Rust functions such as `<[u8]>::align_to::` and +// `<*const u8>::align_offset` aren't _guaranteed_ to compute the largest +// possible middle region, and as such can't be used. +fn u64_align_to_guaranteed(ptr: *const u8, mut len: usize) -> (usize, usize, usize) { + const QWORD_SIZE: usize = mem::size_of::(); + + let offset = ptr as usize % QWORD_SIZE; + + let prefix_len = if intrinsics::unlikely(offset > 0) { QWORD_SIZE - offset } else { 0 }; + + len = match len.checked_sub(prefix_len) { + Some(remaining_len) => remaining_len, + None => return (len, 0, 0), + }; + + let suffix_len = len % QWORD_SIZE; + len -= suffix_len; + + (prefix_len, len, suffix_len) } unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) { @@ -352,7 +369,13 @@ unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) { /// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html /// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html#inpage-nav-3-2-2 pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) { - unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) { + /// Like `ptr::copy(src, dst, len)`, except it uses the Intel-recommended + /// instruction sequence for unaligned writes. + unsafe fn write_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) { + if intrinsics::likely(len == 0) { + return; + } + unsafe { let mut seg_sel: u16 = 0; for off in 0..len { @@ -380,41 +403,15 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) assert!(!src.addr().overflowing_add(len).1); assert!(!dst.addr().overflowing_add(len).1); - if len < 8 { - // Can't align on 8 byte boundary: copy safely byte per byte - unsafe { - copy_bytewise_to_userspace(src, dst, len); - } - } else if len % 8 == 0 && dst.is_aligned_to(8) { - // Copying 8-byte aligned quadwords: copy quad word per quad word - unsafe { - copy_quadwords(src, dst, len); - } - } else { - // Split copies into three parts: - // +--------+ - // | small0 | Chunk smaller than 8 bytes - // +--------+ - // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes - // +--------+ - // | small1 | Chunk smaller than 8 bytes - // +--------+ - let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len); + unsafe { + let (len1, len2, len3) = u64_align_to_guaranteed(dst, len); + let (src1, dst1) = (src, dst); + let (src2, dst2) = (src1.add(len1), dst1.add(len1)); + let (src3, dst3) = (src2.add(len2), dst2.add(len2)); - unsafe { - // Copy small0 - copy_bytewise_to_userspace(src, dst, small0_size); - - // Copy big - let big_src = src.add(small0_size); - let big_dst = dst.add(small0_size); - copy_quadwords(big_src, big_dst, big_size); - - // Copy small1 - let small1_src = src.add(big_size + small0_size); - let small1_dst = dst.add(big_size + small0_size); - copy_bytewise_to_userspace(small1_src, small1_dst, small1_size); - } + write_bytewise_to_userspace(src1, dst1, len1); + copy_quadwords(src2, dst2, len2); + write_bytewise_to_userspace(src3, dst3, len3); } } @@ -434,45 +431,33 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) /// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html /// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) { - // Copies memory region `src..src + len` to the enclave at `dst`. The source memory region - // is: - // - strictly less than 8 bytes in size and may be - // - located at a misaligned memory location - fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) { - let mut tmp_buff = [0u8; 16]; + /// Like `ptr::copy(src, dst, len)`, except it uses only u64-aligned reads. + /// + /// # Safety + /// The source memory region must not straddle an alignment boundary. + unsafe fn read_misaligned_from_userspace(src: *const u8, dst: *mut u8, len: usize) { + if intrinsics::likely(len == 0) { + return; + } unsafe { - // Compute an aligned memory region to read from - // +--------+ <-- aligned_src + aligned_len (8B-aligned) - // | pad1 | - // +--------+ <-- src + len (misaligned) - // | | - // | | - // | | - // +--------+ <-- src (misaligned) - // | pad0 | - // +--------+ <-- aligned_src (8B-aligned) - let pad0_size = src as usize % 8; - let aligned_src = src.sub(pad0_size); - - let pad1_size = 8 - (src.add(len) as usize % 8); - let aligned_len = pad0_size + len + pad1_size; - - debug_assert!(len < 8); - debug_assert_eq!(aligned_src as usize % 8, 0); - debug_assert_eq!(aligned_len % 8, 0); - debug_assert!(aligned_len <= 16); - - // Copy the aligned buffer to a temporary buffer - // Note: copying from a slightly different memory location is a bit odd. In this case it - // can't lead to page faults or inadvertent copying from the enclave as we only ensured - // that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes - // aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made - // for `src + len` - copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len); - - // Copy the correct parts of the temporary buffer to the destination - ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len); + let offset: usize; + let data: u64; + // doing a memory read that's potentially out of bounds for `src`, + // this isn't supported by Rust, so have to use assembly + asm!(" + movl {src:e}, {offset:e} + andl $7, {offset:e} + andq $-8, {src} + movq ({src}), {dst} + ", + src = inout(reg) src => _, + offset = out(reg) offset, + dst = out(reg) data, + options(nostack, att_syntax, readonly, pure) + ); + let data = data.to_le_bytes(); + ptr::copy_nonoverlapping(data.as_ptr().add(offset), dst, len); } } @@ -480,41 +465,19 @@ pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usiz assert!(!dst.is_null()); assert!(is_user_range(src, len)); assert!(is_enclave_range(dst, len)); - assert!(!(src as usize).overflowing_add(len + 8).1); - assert!(!(dst as usize).overflowing_add(len + 8).1); + assert!(len < isize::MAX as usize); + assert!(!(src as usize).overflowing_add(len).1); + assert!(!(dst as usize).overflowing_add(len).1); - if len < 8 { - copy_misaligned_chunk_to_enclave(src, dst, len); - } else if len % 8 == 0 && src as usize % 8 == 0 { - // Copying 8-byte aligned quadwords: copy quad word per quad word - unsafe { - copy_quadwords(src, dst, len); - } - } else { - // Split copies into three parts: - // +--------+ - // | small0 | Chunk smaller than 8 bytes - // +--------+ - // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes - // +--------+ - // | small1 | Chunk smaller than 8 bytes - // +--------+ - let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len); + unsafe { + let (len1, len2, len3) = u64_align_to_guaranteed(src, len); + let (src1, dst1) = (src, dst); + let (src2, dst2) = (src1.add(len1), dst1.add(len1)); + let (src3, dst3) = (src2.add(len2), dst2.add(len2)); - unsafe { - // Copy small0 - copy_misaligned_chunk_to_enclave(src, dst, small0_size); - - // Copy big - let big_src = src.add(small0_size); - let big_dst = dst.add(small0_size); - copy_quadwords(big_src, big_dst, big_size); - - // Copy small1 - let small1_src = src.add(big_size + small0_size); - let small1_dst = dst.add(big_size + small0_size); - copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size); - } + read_misaligned_from_userspace(src1, dst1, len1); + copy_quadwords(src2, dst2, len2); + read_misaligned_from_userspace(src3, dst3, len3); } } @@ -609,9 +572,9 @@ where /// Copies the value from user memory into enclave memory. pub fn to_enclave(&self) -> T { unsafe { - let mut data: T = mem::MaybeUninit::uninit().assume_init(); - copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::()); - data + let mut data = mem::MaybeUninit::uninit(); + copy_from_userspace(self.0.get() as _, data.as_mut_ptr() as _, mem::size_of::()); + data.assume_init() } } } diff --git a/library/std/src/sys/sgx/waitqueue/mod.rs b/library/std/src/sys/sgx/waitqueue/mod.rs index 5e1d859ee99c3..25eca61d67b66 100644 --- a/library/std/src/sys/sgx/waitqueue/mod.rs +++ b/library/std/src/sys/sgx/waitqueue/mod.rs @@ -18,6 +18,7 @@ mod unsafe_list; use crate::num::NonZeroUsize; use crate::ops::{Deref, DerefMut}; +use crate::panic::{self, AssertUnwindSafe}; use crate::time::Duration; use super::abi::thread; @@ -147,7 +148,8 @@ impl WaitQueue { /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait /// until a wakeup event. /// - /// This function does not return until this thread has been awoken. + /// This function does not return until this thread has been awoken. When `before_wait` panics, + /// this function will abort. pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>, before_wait: F) { // very unsafe: check requirements of UnsafeList::push unsafe { @@ -157,8 +159,13 @@ impl WaitQueue { })); let entry = guard.queue.inner.push(&mut entry); drop(guard); - before_wait(); + if let Err(_e) = panic::catch_unwind(AssertUnwindSafe(|| before_wait())) { + rtabort!("Panic before wait on wakeup event") + } while !entry.lock().wake { + // `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure + // the entry is removed from the queue _before_ setting this bool. There are no + // other references to `entry`. // don't panic, this would invalidate `entry` during unwinding let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); rtassert!(eventset & EV_UNPARK == EV_UNPARK); @@ -169,6 +176,7 @@ impl WaitQueue { /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait /// until a wakeup event or timeout. If event was observed, returns true. /// If not, it will remove the calling thread from the wait queue. + /// When `before_wait` panics, this function will abort. pub fn wait_timeout( lock: &SpinMutex>, timeout: Duration, @@ -181,9 +189,13 @@ impl WaitQueue { wake: false, })); let entry_lock = lock.lock().queue.inner.push(&mut entry); - before_wait(); + if let Err(_e) = panic::catch_unwind(AssertUnwindSafe(|| before_wait())) { + rtabort!("Panic before wait on wakeup event or timeout") + } usercalls::wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake); - // acquire the wait queue's lock first to avoid deadlock. + // acquire the wait queue's lock first to avoid deadlock + // and ensure no other function can simultaneously access the list + // (e.g., `notify_one` or `notify_all`) let mut guard = lock.lock(); let success = entry_lock.lock().wake; if !success { @@ -204,8 +216,8 @@ impl WaitQueue { ) -> Result, SpinMutexGuard<'_, WaitVariable>> { // SAFETY: lifetime of the pop() return value is limited to the map // closure (The closure return value is 'static). The underlying - // stack frame won't be freed until after the WaitGuard created below - // is dropped. + // stack frame won't be freed until after the lock on the queue is released + // (i.e., `guard` is dropped). unsafe { let tcs = guard.queue.inner.pop().map(|entry| -> Tcs { let mut entry_guard = entry.lock(); @@ -231,7 +243,7 @@ impl WaitQueue { ) -> Result, SpinMutexGuard<'_, WaitVariable>> { // SAFETY: lifetime of the pop() return values are limited to the // while loop body. The underlying stack frames won't be freed until - // after the WaitGuard created below is dropped. + // after the lock on the queue is released (i.e., `guard` is dropped). unsafe { let mut count = 0; while let Some(entry) = guard.queue.inner.pop() { diff --git a/library/std/src/sys/uefi/alloc.rs b/library/std/src/sys/uefi/alloc.rs new file mode 100644 index 0000000000000..789e3cbd81ade --- /dev/null +++ b/library/std/src/sys/uefi/alloc.rs @@ -0,0 +1,33 @@ +//! Global Allocator for UEFI. +//! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc) + +use crate::alloc::{GlobalAlloc, Layout, System}; + +const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // Return null pointer if boot services are not available + if crate::os::uefi::env::boot_services().is_none() { + return crate::ptr::null_mut(); + } + + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); + // The caller must ensure non-0 layout + unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + // Do nothing if boot services are not available + if crate::os::uefi::env::boot_services().is_none() { + return; + } + + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); + // The caller must ensure non-0 layout + unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) } + } +} diff --git a/library/std/src/sys/uefi/env.rs b/library/std/src/sys/uefi/env.rs new file mode 100644 index 0000000000000..c106d5fed3e1d --- /dev/null +++ b/library/std/src/sys/uefi/env.rs @@ -0,0 +1,9 @@ +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = "uefi"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ".efi"; + pub const EXE_EXTENSION: &str = "efi"; +} diff --git a/library/std/src/sys/uefi/helpers.rs b/library/std/src/sys/uefi/helpers.rs new file mode 100644 index 0000000000000..126661bfc961c --- /dev/null +++ b/library/std/src/sys/uefi/helpers.rs @@ -0,0 +1,141 @@ +//! Contains most of the shared UEFI specific stuff. Some of this might be moved to `std::os::uefi` +//! if needed but no point in adding extra public API when there is not Std support for UEFI in the +//! first place +//! +//! Some Nomenclature +//! * Protocol: +//! - Protocols serve to enable communication between separately built modules, including drivers. +//! - Every protocol has a GUID associated with it. The GUID serves as the name for the protocol. +//! - Protocols are produced and consumed. +//! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles) + +use r_efi::efi::{self, Guid}; + +use crate::mem::{size_of, MaybeUninit}; +use crate::os::uefi; +use crate::ptr::NonNull; +use crate::{ + io::{self, const_io_error}, + os::uefi::env::boot_services, +}; + +const BOOT_SERVICES_UNAVAILABLE: io::Error = + const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available"); + +/// Locate Handles with a particular Protocol GUID +/// Implemented using `EFI_BOOT_SERVICES.LocateHandles()` +/// +/// Returns an array of [Handles](r_efi::efi::Handle) that support a specified protocol. +pub(crate) fn locate_handles(mut guid: Guid) -> io::Result>> { + fn inner( + guid: &mut Guid, + boot_services: NonNull, + buf_size: &mut usize, + buf: *mut r_efi::efi::Handle, + ) -> io::Result<()> { + let r = unsafe { + ((*boot_services.as_ptr()).locate_handle)( + r_efi::efi::BY_PROTOCOL, + guid, + crate::ptr::null_mut(), + buf_size, + buf, + ) + }; + + if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } + } + + let boot_services = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let mut buf_len = 0usize; + + // This should always fail since the size of buffer is 0. This call should update the buf_len + // variable with the required buffer length + match inner(&mut guid, boot_services, &mut buf_len, crate::ptr::null_mut()) { + Ok(()) => unreachable!(), + Err(e) => match e.kind() { + io::ErrorKind::FileTooLarge => {} + _ => return Err(e), + }, + } + + // The returned buf_len is in bytes + assert_eq!(buf_len % size_of::(), 0); + let num_of_handles = buf_len / size_of::(); + let mut buf: Vec = Vec::with_capacity(num_of_handles); + match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) { + Ok(()) => { + // This is safe because the call will succeed only if buf_len >= required length. + // Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written + unsafe { buf.set_len(num_of_handles) }; + Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect()) + } + Err(e) => Err(e), + } +} + +/// Open Protocol on a handle. +/// Internally just a call to `EFI_BOOT_SERVICES.OpenProtocol()`. +/// +/// Queries a handle to determine if it supports a specified protocol. If the protocol is +/// supported by the handle, it opens the protocol on behalf of the calling agent. +pub(crate) fn open_protocol( + handle: NonNull, + mut protocol_guid: Guid, +) -> io::Result> { + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let system_handle = uefi::env::image_handle(); + let mut protocol: MaybeUninit<*mut T> = MaybeUninit::uninit(); + + let r = unsafe { + ((*boot_services.as_ptr()).open_protocol)( + handle.as_ptr(), + &mut protocol_guid, + protocol.as_mut_ptr().cast(), + system_handle.as_ptr(), + crate::ptr::null_mut(), + r_efi::system::OPEN_PROTOCOL_GET_PROTOCOL, + ) + }; + + if r.is_error() { + Err(crate::io::Error::from_raw_os_error(r.as_usize())) + } else { + NonNull::new(unsafe { protocol.assume_init() }) + .ok_or(const_io_error!(io::ErrorKind::Other, "null protocol")) + } +} + +pub(crate) fn create_event( + signal: u32, + tpl: efi::Tpl, + handler: Option, + context: *mut crate::ffi::c_void, +) -> io::Result> { + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let mut event: r_efi::efi::Event = crate::ptr::null_mut(); + let r = unsafe { + let create_event = (*boot_services.as_ptr()).create_event; + (create_event)(signal, tpl, handler, context, &mut event) + }; + if r.is_error() { + Err(crate::io::Error::from_raw_os_error(r.as_usize())) + } else { + NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol")) + } +} + +/// # SAFETY +/// - The supplied event must be valid +pub(crate) unsafe fn close_event(evt: NonNull) -> io::Result<()> { + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let r = unsafe { + let close_event = (*boot_services.as_ptr()).close_event; + (close_event)(evt.as_ptr()) + }; + + if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } +} diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs new file mode 100644 index 0000000000000..097396ae99396 --- /dev/null +++ b/library/std/src/sys/uefi/mod.rs @@ -0,0 +1,243 @@ +//! Platform-specific extensions to `std` for UEFI platforms. +//! +//! Provides access to platform-level information on UEFI platforms, and +//! exposes UEFI-specific functions that would otherwise be inappropriate as +//! part of the core `std` library. +//! +//! It exposes more ways to deal with platform-specific strings ([`OsStr`], +//! [`OsString`]), allows to set permissions more granularly, extract low-level +//! file descriptors from files and sockets, and has platform-specific helpers +//! for spawning processes. +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString + +pub mod alloc; +#[path = "../unsupported/args.rs"] +pub mod args; +#[path = "../unix/cmath.rs"] +pub mod cmath; +pub mod env; +#[path = "../unsupported/fs.rs"] +pub mod fs; +#[path = "../unsupported/io.rs"] +pub mod io; +#[path = "../unsupported/locks/mod.rs"] +pub mod locks; +#[path = "../unsupported/net.rs"] +pub mod net; +#[path = "../unsupported/once.rs"] +pub mod once; +pub mod os; +#[path = "../windows/os_str.rs"] +pub mod os_str; +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +pub mod stdio; +#[path = "../unsupported/thread.rs"] +pub mod thread; +#[path = "../unsupported/thread_local_key.rs"] +pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; +#[path = "../unsupported/time.rs"] +pub mod time; + +mod helpers; + +#[cfg(test)] +mod tests; + +pub type RawOsError = usize; + +use crate::io as std_io; +use crate::os::uefi; +use crate::ptr::NonNull; +use crate::sync::atomic::{AtomicPtr, Ordering}; + +pub mod memchr { + pub use core::slice::memchr::{memchr, memrchr}; +} + +static EXIT_BOOT_SERVICE_EVENT: AtomicPtr = + AtomicPtr::new(crate::ptr::null_mut()); + +/// # SAFETY +/// - must be called only once during runtime initialization. +/// - argc must be 2. +/// - argv must be &[Handle, *mut SystemTable]. +pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { + assert_eq!(argc, 2); + let image_handle = unsafe { NonNull::new(*argv as *mut crate::ffi::c_void).unwrap() }; + let system_table = unsafe { NonNull::new(*argv.add(1) as *mut crate::ffi::c_void).unwrap() }; + unsafe { uefi::env::init_globals(image_handle, system_table) }; + + // Register exit boot services handler + match helpers::create_event( + r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES, + r_efi::efi::TPL_NOTIFY, + Some(exit_boot_service_handler), + crate::ptr::null_mut(), + ) { + Ok(x) => { + if EXIT_BOOT_SERVICE_EVENT + .compare_exchange( + crate::ptr::null_mut(), + x.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .is_err() + { + abort_internal(); + }; + } + Err(_) => abort_internal(), + } +} + +/// # SAFETY +/// this is not guaranteed to run, for example when the program aborts. +/// - must be called only once during runtime cleanup. +pub unsafe fn cleanup() { + if let Some(exit_boot_service_event) = + NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire)) + { + let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + } +} + +#[inline] +pub const fn unsupported() -> std_io::Result { + Err(unsupported_err()) +} + +#[inline] +pub const fn unsupported_err() -> std_io::Error { + std_io::const_io_error!(std_io::ErrorKind::Unsupported, "operation not supported on UEFI",) +} + +pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind { + use crate::io::ErrorKind; + use r_efi::efi::Status; + + match r_efi::efi::Status::from_usize(code) { + Status::ALREADY_STARTED + | Status::COMPROMISED_DATA + | Status::CONNECTION_FIN + | Status::CRC_ERROR + | Status::DEVICE_ERROR + | Status::END_OF_MEDIA + | Status::HTTP_ERROR + | Status::ICMP_ERROR + | Status::INCOMPATIBLE_VERSION + | Status::LOAD_ERROR + | Status::MEDIA_CHANGED + | Status::NO_MAPPING + | Status::NO_MEDIA + | Status::NOT_STARTED + | Status::PROTOCOL_ERROR + | Status::PROTOCOL_UNREACHABLE + | Status::TFTP_ERROR + | Status::VOLUME_CORRUPTED => ErrorKind::Other, + Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => ErrorKind::InvalidData, + Status::ABORTED => ErrorKind::ConnectionAborted, + Status::ACCESS_DENIED => ErrorKind::PermissionDenied, + Status::BUFFER_TOO_SMALL => ErrorKind::FileTooLarge, + Status::CONNECTION_REFUSED => ErrorKind::ConnectionRefused, + Status::CONNECTION_RESET => ErrorKind::ConnectionReset, + Status::END_OF_FILE => ErrorKind::UnexpectedEof, + Status::HOST_UNREACHABLE => ErrorKind::HostUnreachable, + Status::INVALID_PARAMETER => ErrorKind::InvalidInput, + Status::IP_ADDRESS_CONFLICT => ErrorKind::AddrInUse, + Status::NETWORK_UNREACHABLE => ErrorKind::NetworkUnreachable, + Status::NO_RESPONSE => ErrorKind::HostUnreachable, + Status::NOT_FOUND => ErrorKind::NotFound, + Status::NOT_READY => ErrorKind::ResourceBusy, + Status::OUT_OF_RESOURCES => ErrorKind::OutOfMemory, + Status::SECURITY_VIOLATION => ErrorKind::PermissionDenied, + Status::TIMEOUT => ErrorKind::TimedOut, + Status::UNSUPPORTED => ErrorKind::Unsupported, + Status::VOLUME_FULL => ErrorKind::StorageFull, + Status::WRITE_PROTECTED => ErrorKind::ReadOnlyFilesystem, + _ => ErrorKind::Uncategorized, + } +} + +pub fn abort_internal() -> ! { + if let Some(exit_boot_service_event) = + NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) + { + let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + } + + if let (Some(boot_services), Some(handle)) = + (uefi::env::boot_services(), uefi::env::try_image_handle()) + { + let boot_services: NonNull = boot_services.cast(); + let _ = unsafe { + ((*boot_services.as_ptr()).exit)( + handle.as_ptr(), + r_efi::efi::Status::ABORTED, + 0, + crate::ptr::null_mut(), + ) + }; + } + + // In case SystemTable and ImageHandle cannot be reached, use `core::intrinsics::abort` + core::intrinsics::abort(); +} + +// This function is needed by the panic runtime. The symbol is named in +// pre-link args for the target specification, so keep that in sync. +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn __rust_abort() { + abort_internal(); +} + +#[inline] +pub fn hashmap_random_keys() -> (u64, u64) { + get_random().unwrap() +} + +fn get_random() -> Option<(u64, u64)> { + use r_efi::protocols::rng; + + let mut buf = [0u8; 16]; + let handles = helpers::locate_handles(rng::PROTOCOL_GUID).ok()?; + for handle in handles { + if let Ok(protocol) = helpers::open_protocol::(handle, rng::PROTOCOL_GUID) { + let r = unsafe { + ((*protocol.as_ptr()).get_rng)( + protocol.as_ptr(), + crate::ptr::null_mut(), + buf.len(), + buf.as_mut_ptr(), + ) + }; + if r.is_error() { + continue; + } else { + return Some(( + u64::from_le_bytes(buf[..8].try_into().ok()?), + u64::from_le_bytes(buf[8..].try_into().ok()?), + )); + } + } + } + None +} + +/// Disable access to BootServices if `EVT_SIGNAL_EXIT_BOOT_SERVICES` is signaled +extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) { + uefi::env::disable_boot_services(); +} + +pub fn is_interrupted(_code: RawOsError) -> bool { + false +} diff --git a/library/std/src/sys/uefi/os.rs b/library/std/src/sys/uefi/os.rs new file mode 100644 index 0000000000000..e6693db68e641 --- /dev/null +++ b/library/std/src/sys/uefi/os.rs @@ -0,0 +1,237 @@ +use super::{unsupported, RawOsError}; +use crate::error::Error as StdError; +use crate::ffi::{OsStr, OsString}; +use crate::fmt; +use crate::io; +use crate::marker::PhantomData; +use crate::os::uefi; +use crate::path::{self, PathBuf}; +use crate::ptr::NonNull; +use r_efi::efi::Status; + +pub fn errno() -> RawOsError { + 0 +} + +pub fn error_string(errno: RawOsError) -> String { + // Keep the List in Alphabetical Order + // The Messages are taken from UEFI Specification Appendix D - Status Codes + match r_efi::efi::Status::from_usize(errno) { + Status::ABORTED => "The operation was aborted.".to_owned(), + Status::ACCESS_DENIED => "Access was denied.".to_owned(), + Status::ALREADY_STARTED => "The protocol has already been started.".to_owned(), + Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.".to_owned(), + Status::BUFFER_TOO_SMALL => { + "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.".to_owned() + } + Status::COMPROMISED_DATA => { + "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.".to_owned() + } + Status::CONNECTION_FIN => { + "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.".to_owned() + } + Status::CONNECTION_REFUSED => { + "The receiving or transmission operation fails because this connection is refused.".to_owned() + } + Status::CONNECTION_RESET => { + "The connect fails because the connection is reset either by instance itself or the communication peer.".to_owned() + } + Status::CRC_ERROR => "A CRC error was detected.".to_owned(), + Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.".to_owned() + , + Status::END_OF_FILE => { + "The end of the file was reached.".to_owned() + } + Status::END_OF_MEDIA => { + "Beginning or end of media was reached".to_owned() + } + Status::HOST_UNREACHABLE => { + "The remote host is not reachable.".to_owned() + } + Status::HTTP_ERROR => { + "A HTTP error occurred during the network operation.".to_owned() + } + Status::ICMP_ERROR => { + "An ICMP error occurred during the network operation.".to_owned() + } + Status::INCOMPATIBLE_VERSION => { + "The function encountered an internal version that was incompatible with a version requested by the caller.".to_owned() + } + Status::INVALID_LANGUAGE => { + "The language specified was invalid.".to_owned() + } + Status::INVALID_PARAMETER => { + "A parameter was incorrect.".to_owned() + } + Status::IP_ADDRESS_CONFLICT => { + "There is an address conflict address allocation".to_owned() + } + Status::LOAD_ERROR => { + "The image failed to load.".to_owned() + } + Status::MEDIA_CHANGED => { + "The medium in the device has changed since the last access.".to_owned() + } + Status::NETWORK_UNREACHABLE => { + "The network containing the remote host is not reachable.".to_owned() + } + Status::NO_MAPPING => { + "A mapping to a device does not exist.".to_owned() + } + Status::NO_MEDIA => { + "The device does not contain any medium to perform the operation.".to_owned() + } + Status::NO_RESPONSE => { + "The server was not found or did not respond to the request.".to_owned() + } + Status::NOT_FOUND => "The item was not found.".to_owned(), + Status::NOT_READY => { + "There is no data pending upon return.".to_owned() + } + Status::NOT_STARTED => { + "The protocol has not been started.".to_owned() + } + Status::OUT_OF_RESOURCES => { + "A resource has run out.".to_owned() + } + Status::PROTOCOL_ERROR => { + "A protocol error occurred during the network operation.".to_owned() + } + Status::PROTOCOL_UNREACHABLE => { + "An ICMP protocol unreachable error is received.".to_owned() + } + Status::SECURITY_VIOLATION => { + "The function was not performed due to a security violation.".to_owned() + } + Status::TFTP_ERROR => { + "A TFTP error occurred during the network operation.".to_owned() + } + Status::TIMEOUT => "The timeout time expired.".to_owned(), + Status::UNSUPPORTED => { + "The operation is not supported.".to_owned() + } + Status::VOLUME_FULL => { + "There is no more space on the file system.".to_owned() + } + Status::VOLUME_CORRUPTED => { + "An inconstancy was detected on the file system causing the operating to fail.".to_owned() + } + Status::WRITE_PROTECTED => { + "The device cannot be written to.".to_owned() + } + _ => format!("Status: {}", errno), + } +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + self.0 + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result +where + I: Iterator, + T: AsRef, +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "not supported on this platform yet".fmt(f) + } +} + +impl StdError for JoinPathsError {} + +pub fn current_exe() -> io::Result { + unsupported() +} + +pub struct Env(!); + +impl Env { + // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self(inner) = self; + match *inner {} + } +} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.0 + } +} + +impl fmt::Debug for Env { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(inner) = self; + match *inner {} + } +} + +pub fn env() -> Env { + panic!("not supported on this platform") +} + +pub fn getenv(_: &OsStr) -> Option { + None +} + +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) +} + +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) +} + +pub fn temp_dir() -> PathBuf { + panic!("no filesystem on this platform") +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(code: i32) -> ! { + if let (Some(boot_services), Some(handle)) = + (uefi::env::boot_services(), uefi::env::try_image_handle()) + { + let boot_services: NonNull = boot_services.cast(); + let _ = unsafe { + ((*boot_services.as_ptr()).exit)( + handle.as_ptr(), + Status::from_usize(code as usize), + 0, + crate::ptr::null_mut(), + ) + }; + } + crate::intrinsics::abort() +} + +pub fn getpid() -> u32 { + panic!("no pids on this platform") +} diff --git a/library/std/src/sys/uefi/path.rs b/library/std/src/sys/uefi/path.rs new file mode 100644 index 0000000000000..106682eee56b6 --- /dev/null +++ b/library/std/src/sys/uefi/path.rs @@ -0,0 +1,25 @@ +use super::unsupported; +use crate::ffi::OsStr; +use crate::io; +use crate::path::{Path, PathBuf, Prefix}; + +pub const MAIN_SEP_STR: &str = "\\"; +pub const MAIN_SEP: char = '\\'; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'\\' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'\\' +} + +pub fn parse_prefix(_p: &OsStr) -> Option> { + None +} + +pub(crate) fn absolute(_path: &Path) -> io::Result { + unsupported() +} diff --git a/library/std/src/sys/uefi/stdio.rs b/library/std/src/sys/uefi/stdio.rs new file mode 100644 index 0000000000000..a533d8a057506 --- /dev/null +++ b/library/std/src/sys/uefi/stdio.rs @@ -0,0 +1,162 @@ +use crate::io; +use crate::iter::Iterator; +use crate::mem::MaybeUninit; +use crate::os::uefi; +use crate::ptr::NonNull; + +const MAX_BUFFER_SIZE: usize = 8192; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +impl Stdin { + pub const fn new() -> Stdin { + Stdin + } +} + +impl io::Read for Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let st: NonNull = uefi::env::system_table().cast(); + let stdin = unsafe { (*st.as_ptr()).con_in }; + + // Try reading any pending data + let inp = match read_key_stroke(stdin) { + Ok(x) => x, + Err(e) if e == r_efi::efi::Status::NOT_READY => { + // Wait for keypress for new data + wait_stdin(stdin)?; + read_key_stroke(stdin).map_err(|x| io::Error::from_raw_os_error(x.as_usize()))? + } + Err(e) => { + return Err(io::Error::from_raw_os_error(e.as_usize())); + } + }; + + // Check if the key is printiable character + if inp.scan_code != 0x00 { + return Err(io::const_io_error!(io::ErrorKind::Interrupted, "Special Key Press")); + } + + // SAFETY: Iterator will have only 1 character since we are reading only 1 Key + // SAFETY: This character will always be UCS-2 and thus no surrogates. + let ch: char = char::decode_utf16([inp.unicode_char]).next().unwrap().unwrap(); + if ch.len_utf8() > buf.len() { + return Ok(0); + } + + ch.encode_utf8(buf); + + Ok(ch.len_utf8()) + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + let st: NonNull = uefi::env::system_table().cast(); + let stdout = unsafe { (*st.as_ptr()).con_out }; + + write(stdout, buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub const fn new() -> Stderr { + Stderr + } +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + let st: NonNull = uefi::env::system_table().cast(); + let stderr = unsafe { (*st.as_ptr()).std_err }; + + write(stderr, buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +// UCS-2 character should occupy 3 bytes at most in UTF-8 +pub const STDIN_BUF_SIZE: usize = 3; + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} + +pub fn panic_output() -> Option { + uefi::env::try_system_table().map(|_| Stderr::new()) +} + +fn write( + protocol: *mut r_efi::protocols::simple_text_output::Protocol, + buf: &[u8], +) -> io::Result { + let mut utf16 = [0; MAX_BUFFER_SIZE / 2]; + + // Get valid UTF-8 buffer + let utf8 = match crate::str::from_utf8(buf) { + Ok(x) => x, + Err(e) => unsafe { crate::str::from_utf8_unchecked(&buf[..e.valid_up_to()]) }, + }; + // Clip UTF-8 buffer to max UTF-16 buffer we support + let utf8 = &utf8[..utf8.floor_char_boundary(utf16.len() - 1)]; + + for (i, ch) in utf8.encode_utf16().enumerate() { + utf16[i] = ch; + } + + unsafe { simple_text_output(protocol, &mut utf16) }?; + + Ok(utf8.len()) +} + +unsafe fn simple_text_output( + protocol: *mut r_efi::protocols::simple_text_output::Protocol, + buf: &mut [u16], +) -> io::Result<()> { + let res = unsafe { ((*protocol).output_string)(protocol, buf.as_mut_ptr()) }; + if res.is_error() { Err(io::Error::from_raw_os_error(res.as_usize())) } else { Ok(()) } +} + +fn wait_stdin(stdin: *mut r_efi::protocols::simple_text_input::Protocol) -> io::Result<()> { + let boot_services: NonNull = + uefi::env::boot_services().unwrap().cast(); + let wait_for_event = unsafe { (*boot_services.as_ptr()).wait_for_event }; + let wait_for_key_event = unsafe { (*stdin).wait_for_key }; + + let r = { + let mut x: usize = 0; + (wait_for_event)(1, [wait_for_key_event].as_mut_ptr(), &mut x) + }; + if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } +} + +fn read_key_stroke( + stdin: *mut r_efi::protocols::simple_text_input::Protocol, +) -> Result { + let mut input_key: MaybeUninit = + MaybeUninit::uninit(); + + let r = unsafe { ((*stdin).read_key_stroke)(stdin, input_key.as_mut_ptr()) }; + + if r.is_error() { + Err(r) + } else { + let input_key = unsafe { input_key.assume_init() }; + Ok(input_key) + } +} diff --git a/library/std/src/sys/uefi/tests.rs b/library/std/src/sys/uefi/tests.rs new file mode 100644 index 0000000000000..8806eda3ac0a6 --- /dev/null +++ b/library/std/src/sys/uefi/tests.rs @@ -0,0 +1,21 @@ +use super::alloc::*; + +#[test] +fn align() { + // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be + // statically verified. + assert_eq!(POOL_ALIGNMENT, 8); + + // Loop over allocation-request sizes from 0-256 and alignments from 1-128, and verify + // that in case of overalignment there is at least space for one additional pointer to + // store in the allocation. + for i in 0..256 { + for j in &[1, 2, 4, 8, 16, 32, 64, 128] { + if *j <= 8 { + assert_eq!(align_size(i, *j), i); + } else { + assert!(align_size(i, *j) > i + std::mem::size_of::<*mut ()>()); + } + } + } +} diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index eafd6821f540a..2da17fabcd64d 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -70,7 +70,9 @@ impl DoubleEndedIterator for Args { target_os = "redox", target_os = "vxworks", target_os = "horizon", + target_os = "aix", target_os = "nto", + target_os = "hurd", ))] mod imp { use super::Args; diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index 929e9dae73868..3bb492fa98bcf 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -152,6 +152,17 @@ pub mod os { pub const EXE_EXTENSION: &str = "elf"; } +#[cfg(target_os = "hurd")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "hurd"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "vita")] pub mod os { pub const FAMILY: &str = "unix"; @@ -250,3 +261,14 @@ pub mod os { pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } + +#[cfg(target_os = "aix")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "aix"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".a"; + pub const DLL_EXTENSION: &str = "a"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 85e020ae41328..6c4f408426a94 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -13,14 +13,16 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; target_os = "android", target_os = "linux", target_os = "emscripten", - target_os = "l4re" + target_os = "l4re", + target_os = "hurd", ))] use libc::off64_t; #[cfg(not(any( target_os = "linux", target_os = "emscripten", target_os = "l4re", - target_os = "android" + target_os = "android", + target_os = "hurd", )))] use libc::off_t as off64_t; @@ -124,9 +126,9 @@ impl FileDesc { } pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { - #[cfg(not(any(target_os = "linux", target_os = "android")))] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "hurd")))] use libc::pread as pread64; - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "hurd"))] use libc::pread64; unsafe { @@ -160,6 +162,7 @@ impl FileDesc { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "netbsd", @@ -181,6 +184,7 @@ impl FileDesc { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "ios", target_os = "tvos", @@ -281,9 +285,9 @@ impl FileDesc { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { - #[cfg(not(any(target_os = "linux", target_os = "android")))] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "hurd")))] use libc::pwrite as pwrite64; - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "hurd"))] use libc::pwrite64; unsafe { @@ -301,6 +305,7 @@ impl FileDesc { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "netbsd", @@ -322,6 +327,7 @@ impl FileDesc { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "ios", target_os = "tvos", diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 61ea87a5b0cec..e1c58f2ba3c37 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -39,9 +39,14 @@ use libc::{c_int, mode_t}; all(target_os = "linux", target_env = "gnu") ))] use libc::c_char; -#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] +#[cfg(any( + target_os = "linux", + target_os = "emscripten", + target_os = "android", + target_os = "hurd", +))] use libc::dirfd; -#[cfg(any(target_os = "linux", target_os = "emscripten"))] +#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "hurd"))] use libc::fstatat64; #[cfg(any( target_os = "android", @@ -49,11 +54,12 @@ use libc::fstatat64; target_os = "fuchsia", target_os = "redox", target_os = "illumos", + target_os = "aix", target_os = "nto", target_os = "vita", ))] use libc::readdir as readdir64; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "hurd"))] use libc::readdir64; #[cfg(any(target_os = "emscripten", target_os = "l4re"))] use libc::readdir64_r; @@ -66,8 +72,10 @@ use libc::readdir64_r; target_os = "l4re", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", )))] use libc::readdir_r as readdir64_r; #[cfg(target_os = "android")] @@ -79,13 +87,19 @@ use libc::{ target_os = "linux", target_os = "emscripten", target_os = "l4re", - target_os = "android" + target_os = "android", + target_os = "hurd", )))] use libc::{ dirent as dirent64, fstat as fstat64, ftruncate as ftruncate64, lseek as lseek64, lstat as lstat64, off_t as off64_t, open as open64, stat as stat64, }; -#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))] +#[cfg(any( + target_os = "linux", + target_os = "emscripten", + target_os = "l4re", + target_os = "hurd" +))] use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64}; pub use crate::sys_common::fs::try_exists; @@ -276,8 +290,10 @@ unsafe impl Sync for Dir {} target_os = "illumos", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", - target_os = "vita" + target_os = "vita", + target_os = "hurd", ))] pub struct DirEntry { dir: Arc, @@ -298,16 +314,19 @@ pub struct DirEntry { target_os = "illumos", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", ))] struct dirent64_min { d_ino: u64, #[cfg(not(any( target_os = "solaris", target_os = "illumos", + target_os = "aix", target_os = "nto", - target_os = "vita" + target_os = "vita", )))] d_type: u8, } @@ -319,8 +338,10 @@ struct dirent64_min { target_os = "illumos", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", )))] pub struct DirEntry { dir: Arc, @@ -449,13 +470,29 @@ impl FileAttr { } } -#[cfg(not(any(target_os = "netbsd", target_os = "nto")))] +#[cfg(target_os = "aix")] +impl FileAttr { + pub fn modified(&self) -> io::Result { + Ok(SystemTime::new(self.stat.st_mtime.tv_sec as i64, self.stat.st_mtime.tv_nsec as i64)) + } + + pub fn accessed(&self) -> io::Result { + Ok(SystemTime::new(self.stat.st_atime.tv_sec as i64, self.stat.st_atime.tv_nsec as i64)) + } + + pub fn created(&self) -> io::Result { + Ok(SystemTime::new(self.stat.st_ctime.tv_sec as i64, self.stat.st_ctime.tv_nsec as i64)) + } +} + +#[cfg(not(any(target_os = "netbsd", target_os = "nto", target_os = "aix")))] impl FileAttr { #[cfg(not(any( target_os = "vxworks", target_os = "espidf", target_os = "horizon", - target_os = "vita" + target_os = "vita", + target_os = "hurd", )))] pub fn modified(&self) -> io::Result { #[cfg(target_pointer_width = "32")] @@ -473,7 +510,7 @@ impl FileAttr { Ok(SystemTime::new(self.stat.st_mtime as i64, 0)) } - #[cfg(target_os = "horizon")] + #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn modified(&self) -> io::Result { Ok(SystemTime::from(self.stat.st_mtim)) } @@ -482,7 +519,8 @@ impl FileAttr { target_os = "vxworks", target_os = "espidf", target_os = "horizon", - target_os = "vita" + target_os = "vita", + target_os = "hurd", )))] pub fn accessed(&self) -> io::Result { #[cfg(target_pointer_width = "32")] @@ -500,7 +538,7 @@ impl FileAttr { Ok(SystemTime::new(self.stat.st_atime as i64, 0)) } - #[cfg(target_os = "horizon")] + #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn accessed(&self) -> io::Result { Ok(SystemTime::from(self.stat.st_atim)) } @@ -654,8 +692,10 @@ impl Iterator for ReadDir { target_os = "fuchsia", target_os = "redox", target_os = "illumos", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", ))] fn next(&mut self) -> Option> { if self.end_of_stream { @@ -730,6 +770,7 @@ impl Iterator for ReadDir { #[cfg(not(any( target_os = "solaris", target_os = "illumos", + target_os = "aix", target_os = "nto", )))] d_type: *offset_ptr!(entry_ptr, d_type) as u8, @@ -754,8 +795,10 @@ impl Iterator for ReadDir { target_os = "fuchsia", target_os = "redox", target_os = "illumos", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", )))] fn next(&mut self) -> Option> { if self.end_of_stream { @@ -809,7 +852,12 @@ impl DirEntry { } #[cfg(all( - any(target_os = "linux", target_os = "emscripten", target_os = "android"), + any( + target_os = "linux", + target_os = "emscripten", + target_os = "android", + target_os = "hurd", + ), not(miri) ))] pub fn metadata(&self) -> io::Result { @@ -833,7 +881,12 @@ impl DirEntry { } #[cfg(any( - not(any(target_os = "linux", target_os = "emscripten", target_os = "android")), + not(any( + target_os = "linux", + target_os = "emscripten", + target_os = "android", + target_os = "hurd", + )), miri ))] pub fn metadata(&self) -> io::Result { @@ -845,6 +898,7 @@ impl DirEntry { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", target_os = "nto", target_os = "vita", ))] @@ -857,6 +911,7 @@ impl DirEntry { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", target_os = "nto", target_os = "vita", )))] @@ -891,7 +946,9 @@ impl DirEntry { target_os = "espidf", target_os = "horizon", target_os = "vita", + target_os = "aix", target_os = "nto", + target_os = "hurd", ))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 @@ -947,8 +1004,10 @@ impl DirEntry { target_os = "illumos", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", )))] fn name_cstr(&self) -> &CStr { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } @@ -960,8 +1019,10 @@ impl DirEntry { target_os = "illumos", target_os = "fuchsia", target_os = "redox", + target_os = "aix", target_os = "nto", target_os = "vita", + target_os = "hurd", ))] fn name_cstr(&self) -> &CStr { &self.name @@ -1131,6 +1192,7 @@ impl File { target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "hurd", ))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) @@ -1146,6 +1208,7 @@ impl File { target_os = "openbsd", target_os = "watchos", target_os = "nto", + target_os = "hurd", )))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) @@ -1357,6 +1420,7 @@ impl FromInner for File { } impl AsFd for File { + #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } @@ -1456,6 +1520,7 @@ impl fmt::Debug for File { target_os = "linux", target_os = "macos", target_os = "freebsd", + target_os = "hurd", target_os = "netbsd", target_os = "openbsd", target_os = "vxworks" @@ -1477,6 +1542,7 @@ impl fmt::Debug for File { target_os = "linux", target_os = "macos", target_os = "freebsd", + target_os = "hurd", target_os = "netbsd", target_os = "openbsd", target_os = "vxworks" @@ -1989,6 +2055,7 @@ mod remove_dir_impl { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", ))] fn is_dir(_ent: &DirEntry) -> Option { None @@ -1999,6 +2066,7 @@ mod remove_dir_impl { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", )))] fn is_dir(ent: &DirEntry) -> Option { match ent.entry.d_type { diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 4d17a1b000229..18acd5ecccd5c 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -59,9 +59,9 @@ use crate::ptr; use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use crate::sys::cvt; use crate::sys::weak::syscall; -#[cfg(not(all(target_os = "linux", target_env = "gnu")))] +#[cfg(not(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd")))] use libc::sendfile as sendfile64; -#[cfg(all(target_os = "linux", target_env = "gnu"))] +#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd"))] use libc::sendfile64; use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV}; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 692d3ab7cc970..01d8217342ce4 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -204,6 +204,10 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { } if let Some(handler) = handler { rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); + #[cfg(target_os = "hurd")] + { + rtassert!(signal(libc::SIGLOST, handler) != libc::SIG_ERR); + } } } } @@ -274,6 +278,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ENETUNREACH => NetworkUnreachable, libc::ENOTCONN => NotConnected, libc::ENOTDIR => NotADirectory, + #[cfg(not(target_os = "aix"))] libc::ENOTEMPTY => DirectoryNotEmpty, libc::EPIPE => BrokenPipe, libc::EROFS => ReadOnlyFilesystem, diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 48f163b6db098..f450d708dae62 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -75,6 +75,7 @@ impl Socket { target_os = "dragonfly", target_os = "freebsd", target_os = "illumos", + target_os = "hurd", target_os = "linux", target_os = "netbsd", target_os = "openbsd", @@ -114,6 +115,7 @@ impl Socket { target_os = "freebsd", target_os = "illumos", target_os = "linux", + target_os = "hurd", target_os = "netbsd", target_os = "openbsd", target_os = "nto", @@ -220,6 +222,7 @@ impl Socket { target_os = "freebsd", target_os = "illumos", target_os = "linux", + target_os = "hurd", target_os = "netbsd", target_os = "openbsd", ))] { diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 57e1a36dace9b..dc3c037c0cb78 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -46,7 +46,8 @@ extern "C" { target_os = "linux", target_os = "emscripten", target_os = "fuchsia", - target_os = "l4re" + target_os = "l4re", + target_os = "hurd", ), link_name = "__errno_location" )] @@ -73,6 +74,7 @@ extern "C" { link_name = "__error" )] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] + #[cfg_attr(target_os = "aix", link_name = "_Errno")] fn errno_location() -> *mut c_int; } @@ -121,7 +123,10 @@ pub fn set_errno(e: i32) { pub fn error_string(errno: i32) -> String { extern "C" { #[cfg_attr( - all(any(target_os = "linux", target_env = "newlib"), not(target_env = "ohos")), + all( + any(target_os = "linux", target_os = "hurd", target_env = "newlib"), + not(target_env = "ohos") + ), link_name = "__xpg_strerror_r" )] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; @@ -250,6 +255,41 @@ impl StdError for JoinPathsError { } } +#[cfg(target_os = "aix")] +pub fn current_exe() -> io::Result { + use crate::io::ErrorKind; + + #[cfg(test)] + use realstd::env; + + #[cfg(not(test))] + use crate::env; + + let exe_path = env::args().next().ok_or(io::const_io_error!( + ErrorKind::NotFound, + "an executable path was not found because no arguments were provided through argv" + ))?; + let path = PathBuf::from(exe_path); + if path.is_absolute() { + return path.canonicalize(); + } + // Search PWD to infer current_exe. + if let Some(pstr) = path.to_str() && pstr.contains("/") { + return getcwd().map(|cwd| cwd.join(path))?.canonicalize(); + } + // Search PATH to infer current_exe. + if let Some(p) = getenv(OsStr::from_bytes("PATH".as_bytes())) { + for search_path in split_paths(&p) { + let pb = search_path.join(&path); + if pb.is_file() && let Ok(metadata) = crate::fs::metadata(&pb) && + metadata.permissions().mode() & 0o111 != 0 { + return pb.canonicalize(); + } + } + } + Err(io::const_io_error!(ErrorKind::NotFound, "an executable path was not found")) +} + #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] pub fn current_exe() -> io::Result { unsafe { @@ -359,7 +399,12 @@ pub fn current_exe() -> io::Result { } } -#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] +#[cfg(any( + target_os = "linux", + target_os = "hurd", + target_os = "android", + target_os = "emscripten" +))] pub fn current_exe() -> io::Result { match crate::fs::read_link("/proc/self/exe") { Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::const_io_error!( diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs index 938a46bfdd833..33db24e77e4da 100644 --- a/library/std/src/sys/unix/pipe.rs +++ b/library/std/src/sys/unix/pipe.rs @@ -3,7 +3,7 @@ use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; use crate::sys::{cvt, cvt_r}; -use crate::sys_common::IntoInner; +use crate::sys_common::{FromInner, IntoInner}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -21,6 +21,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", + target_os = "hurd", target_os = "linux", target_os = "netbsd", target_os = "openbsd", @@ -158,3 +159,9 @@ impl FromRawFd for AnonPipe { Self(FromRawFd::from_raw_fd(raw_fd)) } } + +impl FromInner for AnonPipe { + fn from_inner(fd: FileDesc) -> Self { + Self(fd) + } +} diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index f729da4477462..1ca11a7f9d763 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -586,6 +586,23 @@ impl fmt::Debug for Command { if let Some(ref cwd) = self.cwd { write!(f, "cd {cwd:?} && ")?; } + if self.env.does_clear() { + write!(f, "env -i ")?; + // Altered env vars will be printed next, that should exactly work as expected. + } else { + // Removed env vars need the command to be wrapped in `env`. + let mut any_removed = false; + for (key, value_opt) in self.get_envs() { + if value_opt.is_none() { + if !any_removed { + write!(f, "env ")?; + any_removed = true; + } + write!(f, "-u {} ", key.to_string_lossy())?; + } + } + } + // Altered env vars can just be added in front of the program. for (key, value_opt) in self.get_envs() { if let Some(value) = value_opt { write!(f, "{}={value:?} ", key.to_string_lossy())?; diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 75b5406450195..564f8c482902b 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -374,6 +374,13 @@ impl Command { return Err(io::Error::last_os_error()); } } + #[cfg(target_os = "hurd")] + { + let ret = sys::signal(libc::SIGLOST, libc::SIG_DFL); + if ret == libc::SIG_ERR { + return Err(io::Error::last_os_error()); + } + } } } @@ -620,6 +627,10 @@ impl Command { let mut default_set = MaybeUninit::::uninit(); cvt(sigemptyset(default_set.as_mut_ptr()))?; cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?; + #[cfg(target_os = "hurd")] + { + cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGLOST))?; + } cvt_nz(libc::posix_spawnattr_setsigdefault( attrs.0.as_mut_ptr(), default_set.as_ptr(), @@ -993,6 +1004,8 @@ fn signal_string(signal: i32) -> &'static str { target_os = "dragonfly" ))] libc::SIGINFO => " (SIGINFO)", + #[cfg(target_os = "hurd")] + libc::SIGLOST => " (SIGLOST)", _ => "", } } diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index b59d4ba26afb9..73c530786b2fe 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -32,6 +32,7 @@ impl Drop for Handler { target_os = "macos", target_os = "dragonfly", target_os = "freebsd", + target_os = "hurd", target_os = "solaris", target_os = "illumos", target_os = "netbsd", @@ -193,6 +194,7 @@ mod imp { target_os = "macos", target_os = "dragonfly", target_os = "freebsd", + target_os = "hurd", target_os = "solaris", target_os = "illumos", target_os = "netbsd", diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 2afec897a884f..e667f34aece05 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -216,7 +216,9 @@ impl Thread { target_os = "l4re", target_os = "emscripten", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "hurd", + target_os = "aix", ))] pub fn set_name(_name: &CStr) { // Newlib, Emscripten, and VxWorks have no way to set a thread name. @@ -309,32 +311,47 @@ pub fn available_parallelism() -> io::Result { target_os = "android", target_os = "emscripten", target_os = "fuchsia", + target_os = "hurd", target_os = "ios", target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "solaris", target_os = "illumos", + target_os = "aix", ))] { + #[allow(unused_assignments)] + #[allow(unused_mut)] + let mut quota = usize::MAX; + #[cfg(any(target_os = "android", target_os = "linux"))] { - let quota = cgroups::quota().max(1); + quota = cgroups::quota().max(1); let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; unsafe { if libc::sched_getaffinity(0, mem::size_of::(), &mut set) == 0 { let count = libc::CPU_COUNT(&set) as usize; let count = count.min(quota); - // reported to occur on MIPS kernels older than our minimum supported kernel version for those targets - let count = NonZeroUsize::new(count) - .expect("CPU count must be > 0. This may be a bug in sched_getaffinity(); try upgrading the kernel."); - return Ok(count); + + // According to sched_getaffinity's API it should always be non-zero, but + // some old MIPS kernels were buggy and zero-initialized the mask if + // none was explicitly set. + // In that case we use the sysconf fallback. + if let Some(count) = NonZeroUsize::new(count) { + return Ok(count) + } } } } match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { -1 => Err(io::Error::last_os_error()), 0 => Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")), - cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), + cpus => { + let count = cpus as usize; + // Cover the unusual situation where we were able to get the quota but not the affinity mask + let count = count.min(quota); + Ok(unsafe { NonZeroUsize::new_unchecked(count) }) + } } } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { use crate::ptr; @@ -692,6 +709,7 @@ mod cgroups { #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), + not(target_os = "hurd"), not(target_os = "macos"), not(target_os = "netbsd"), not(target_os = "openbsd"), @@ -712,6 +730,7 @@ pub mod guard { #[cfg(any( target_os = "linux", target_os = "freebsd", + target_os = "hurd", target_os = "macos", target_os = "netbsd", target_os = "openbsd", @@ -768,6 +787,7 @@ pub mod guard { #[cfg(any( target_os = "android", target_os = "freebsd", + target_os = "hurd", target_os = "linux", target_os = "netbsd", target_os = "l4re" @@ -905,6 +925,7 @@ pub mod guard { #[cfg(any( target_os = "android", target_os = "freebsd", + target_os = "hurd", target_os = "linux", target_os = "netbsd", target_os = "l4re" @@ -936,7 +957,7 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackptr, &mut size), 0); let stackaddr = stackptr.addr(); - ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd")) { + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { Some(stackaddr - guardsize..stackaddr) } else if cfg!(all(target_os = "linux", target_env = "musl")) { Some(stackaddr - guardsize..stackaddr) diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 236d2f2ee2928..a0117e1d165ca 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -11,28 +11,47 @@ // Note, however, that we run on lots older linuxes, as well as cross // compiling from a newer linux to an older linux, so we also have a // fallback implementation to use as well. -#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox"))] +#[allow(unexpected_cfgs)] +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))] +// FIXME: The Rust compiler currently omits weakly function definitions (i.e., +// __cxa_thread_atexit_impl) and its metadata from LLVM IR. +#[no_sanitize(cfi, kcfi)] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local_dtor::register_dtor_fallback; + /// This is necessary because the __cxa_thread_atexit_impl implementation + /// std links to by default may be a C or C++ implementation that was not + /// compiled using the Clang integer normalization option. + #[cfg(not(sanitizer_cfi_normalize_integers))] + #[cfi_encoding = "i"] + #[repr(transparent)] + pub struct c_int(pub libc::c_int); + extern "C" { #[linkage = "extern_weak"] static __dso_handle: *mut u8; #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; + static __cxa_thread_atexit_impl: Option< + extern "C" fn( + unsafe extern "C" fn(*mut libc::c_void), + *mut libc::c_void, + *mut libc::c_void, + ) -> c_int, + >; } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern "C" fn( - dtor: unsafe extern "C" fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8, - ) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)( - dtor, - t, - &__dso_handle as *const _ as *mut _, - ); + + if let Some(f) = __cxa_thread_atexit_impl { + unsafe { + f( + mem::transmute::< + unsafe extern "C" fn(*mut u8), + unsafe extern "C" fn(*mut libc::c_void), + >(dtor), + t.cast(), + &__dso_handle as *const _ as *mut _, + ); + } return; } register_dtor_fallback(t, dtor); @@ -48,7 +67,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { // workaround below is to register, via _tlv_atexit, a custom DTOR list once per // thread. thread_local dtors are pushed to the DTOR list without calling // _tlv_atexit. -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::cell::Cell; use crate::mem; @@ -83,7 +102,12 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { } } -#[cfg(any(target_os = "vxworks", target_os = "horizon", target_os = "emscripten"))] +#[cfg(any( + target_os = "vxworks", + target_os = "horizon", + target_os = "emscripten", + target_os = "aix" +))] #[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten) pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::sys_common::thread_local_dtor::register_dtor_fallback; diff --git a/library/std/src/sys/unix/thread_parking/darwin.rs b/library/std/src/sys/unix/thread_parking/darwin.rs index b709fada3b4a8..8231f3cba2d3c 100644 --- a/library/std/src/sys/unix/thread_parking/darwin.rs +++ b/library/std/src/sys/unix/thread_parking/darwin.rs @@ -2,8 +2,7 @@ //! //! Darwin actually has futex syscalls (`__ulock_wait`/`__ulock_wake`), but they //! cannot be used in `std` because they are non-public (their use will lead to -//! rejection from the App Store) and because they are only available starting -//! with macOS version 10.12, even though the minimum target version is 10.7. +//! rejection from the App Store). //! //! Therefore, we need to look for other synchronization primitives. Luckily, Darwin //! supports semaphores, which allow us to implement the behaviour we need with diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 17b4130c20241..4fe61b28488b4 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -35,7 +35,7 @@ pub(in crate::sys::unix) struct Timespec { } impl SystemTime { - #[cfg_attr(target_os = "horizon", allow(unused))] + #[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))] pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime { SystemTime { t: Timespec::new(tv_sec, tv_nsec) } } diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 5cbb5cb65ba8d..5919cc506d921 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -82,31 +82,99 @@ pub fn is_interrupted(errno: i32) -> bool { } pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { - use std_io::ErrorKind::*; - if errno > u16::MAX as i32 || errno < 0 { - return Uncategorized; + use std_io::ErrorKind; + + let Ok(errno) = u16::try_from(errno) else { + return ErrorKind::Uncategorized; + }; + + macro_rules! match_errno { + ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => { + match errno { + $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*, + _ => ErrorKind::$wildcard, + } + }; } - match errno { - e if e == wasi::ERRNO_CONNREFUSED.raw().into() => ConnectionRefused, - e if e == wasi::ERRNO_CONNRESET.raw().into() => ConnectionReset, - e if e == wasi::ERRNO_PERM.raw().into() || e == wasi::ERRNO_ACCES.raw().into() => { - PermissionDenied - } - e if e == wasi::ERRNO_PIPE.raw().into() => BrokenPipe, - e if e == wasi::ERRNO_NOTCONN.raw().into() => NotConnected, - e if e == wasi::ERRNO_CONNABORTED.raw().into() => ConnectionAborted, - e if e == wasi::ERRNO_ADDRNOTAVAIL.raw().into() => AddrNotAvailable, - e if e == wasi::ERRNO_ADDRINUSE.raw().into() => AddrInUse, - e if e == wasi::ERRNO_NOENT.raw().into() => NotFound, - e if e == wasi::ERRNO_INTR.raw().into() => Interrupted, - e if e == wasi::ERRNO_INVAL.raw().into() => InvalidInput, - e if e == wasi::ERRNO_TIMEDOUT.raw().into() => TimedOut, - e if e == wasi::ERRNO_EXIST.raw().into() => AlreadyExists, - e if e == wasi::ERRNO_AGAIN.raw().into() => WouldBlock, - e if e == wasi::ERRNO_NOSYS.raw().into() => Unsupported, - e if e == wasi::ERRNO_NOMEM.raw().into() => OutOfMemory, - _ => Uncategorized, + match_errno! { + ERRNO_2BIG => ArgumentListTooLong, + ERRNO_ACCES => PermissionDenied, + ERRNO_ADDRINUSE => AddrInUse, + ERRNO_ADDRNOTAVAIL => AddrNotAvailable, + ERRNO_AFNOSUPPORT => Unsupported, + ERRNO_AGAIN => WouldBlock, + // ALREADY => "connection already in progress", + // BADF => "bad file descriptor", + // BADMSG => "bad message", + ERRNO_BUSY => ResourceBusy, + // CANCELED => "operation canceled", + // CHILD => "no child processes", + ERRNO_CONNABORTED => ConnectionAborted, + ERRNO_CONNREFUSED => ConnectionRefused, + ERRNO_CONNRESET => ConnectionReset, + ERRNO_DEADLK => Deadlock, + // DESTADDRREQ => "destination address required", + ERRNO_DOM => InvalidInput, + // DQUOT => /* reserved */, + ERRNO_EXIST => AlreadyExists, + // FAULT => "bad address", + ERRNO_FBIG => FileTooLarge, + ERRNO_HOSTUNREACH => HostUnreachable, + // IDRM => "identifier removed", + // ILSEQ => "illegal byte sequence", + // INPROGRESS => "operation in progress", + ERRNO_INTR => Interrupted, + ERRNO_INVAL => InvalidInput, + ERRNO_IO => Uncategorized, + // ISCONN => "socket is connected", + ERRNO_ISDIR => IsADirectory, + ERRNO_LOOP => FilesystemLoop, + // MFILE => "file descriptor value too large", + ERRNO_MLINK => TooManyLinks, + // MSGSIZE => "message too large", + // MULTIHOP => /* reserved */, + ERRNO_NAMETOOLONG => InvalidFilename, + ERRNO_NETDOWN => NetworkDown, + // NETRESET => "connection aborted by network", + ERRNO_NETUNREACH => NetworkUnreachable, + // NFILE => "too many files open in system", + // NOBUFS => "no buffer space available", + ERRNO_NODEV => NotFound, + ERRNO_NOENT => NotFound, + // NOEXEC => "executable file format error", + // NOLCK => "no locks available", + // NOLINK => /* reserved */, + ERRNO_NOMEM => OutOfMemory, + // NOMSG => "no message of the desired type", + // NOPROTOOPT => "protocol not available", + ERRNO_NOSPC => StorageFull, + ERRNO_NOSYS => Unsupported, + ERRNO_NOTCONN => NotConnected, + ERRNO_NOTDIR => NotADirectory, + ERRNO_NOTEMPTY => DirectoryNotEmpty, + // NOTRECOVERABLE => "state not recoverable", + // NOTSOCK => "not a socket", + ERRNO_NOTSUP => Unsupported, + // NOTTY => "inappropriate I/O control operation", + ERRNO_NXIO => NotFound, + // OVERFLOW => "value too large to be stored in data type", + // OWNERDEAD => "previous owner died", + ERRNO_PERM => PermissionDenied, + ERRNO_PIPE => BrokenPipe, + // PROTO => "protocol error", + ERRNO_PROTONOSUPPORT => Unsupported, + // PROTOTYPE => "protocol wrong type for socket", + // RANGE => "result too large", + ERRNO_ROFS => ReadOnlyFilesystem, + ERRNO_SPIPE => NotSeekable, + ERRNO_SRCH => NotFound, + // STALE => /* reserved */, + ERRNO_TIMEDOUT => TimedOut, + ERRNO_TXTBSY => ResourceBusy, + ERRNO_XDEV => CrossesDevices, + ERRNO_NOTCAPABLE => PermissionDenied, + _ => Uncategorized, } } @@ -124,6 +192,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { return ret; } +#[inline] fn err2io(err: wasi::Errno) -> std_io::Error { std_io::Error::from_raw_os_error(err.raw().into()) } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index d9ccba0e9da76..a349e24b03951 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -46,9 +46,9 @@ pub use FD_SET as fd_set; pub use LINGER as linger; pub use TIMEVAL as timeval; -pub type CONDITION_VARIABLE = RTL_CONDITION_VARIABLE; -pub type SRWLOCK = RTL_SRWLOCK; -pub type INIT_ONCE = RTL_RUN_ONCE; +// https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170 +pub const EXIT_SUCCESS: u32 = 0; +pub const EXIT_FAILURE: u32 = 1; pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() }; pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() }; @@ -224,7 +224,7 @@ pub unsafe extern "system" fn ReadFileEx( ) -> BOOL { windows_sys::ReadFileEx( hFile.as_raw_handle(), - lpBuffer, + lpBuffer.cast::(), nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine, diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 5469ba42eb11a..0aca37e2d454e 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -1,3 +1,6 @@ +--out windows_sys.rs +--config flatten std +--filter // tidy-alphabetical-start Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION @@ -2108,7 +2111,6 @@ Windows.Win32.Networking.WinSock.WSABASEERR Windows.Win32.Networking.WinSock.WSABUF Windows.Win32.Networking.WinSock.WSACleanup Windows.Win32.Networking.WinSock.WSADATA -Windows.Win32.Networking.WinSock.WSADATA Windows.Win32.Networking.WinSock.WSADuplicateSocketW Windows.Win32.Networking.WinSock.WSAEACCES Windows.Win32.Networking.WinSock.WSAEADDRINUSE @@ -2328,7 +2330,6 @@ Windows.Win32.Storage.FileSystem.FileStandardInfo Windows.Win32.Storage.FileSystem.FileStorageInfo Windows.Win32.Storage.FileSystem.FileStreamInfo Windows.Win32.Storage.FileSystem.FindClose -Windows.Win32.Storage.FileSystem.FindFileHandle Windows.Win32.Storage.FileSystem.FindFirstFileW Windows.Win32.Storage.FileSystem.FindNextFileW Windows.Win32.Storage.FileSystem.FlushFileBuffers @@ -2420,8 +2421,6 @@ Windows.Win32.System.Console.STD_OUTPUT_HANDLE Windows.Win32.System.Console.WriteConsoleW Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128 Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT @@ -2435,7 +2434,6 @@ Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS Windows.Win32.System.Diagnostics.Debug.FormatMessageW Windows.Win32.System.Diagnostics.Debug.M128A Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT -Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT Windows.Win32.System.Environment.FreeEnvironmentStringsW Windows.Win32.System.Environment.GetCommandLineW Windows.Win32.System.Environment.GetCurrentDirectoryW @@ -2456,7 +2454,6 @@ Windows.Win32.System.Kernel.ExceptionContinueExecution Windows.Win32.System.Kernel.ExceptionContinueSearch Windows.Win32.System.Kernel.ExceptionNestedException Windows.Win32.System.Kernel.FLOATING_SAVE_AREA -Windows.Win32.System.Kernel.FLOATING_SAVE_AREA Windows.Win32.System.Kernel.OBJ_DONT_REPARSE Windows.Win32.System.LibraryLoader.GetModuleFileNameW Windows.Win32.System.LibraryLoader.GetModuleHandleA @@ -2482,6 +2479,7 @@ Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime Windows.Win32.System.SystemInformation.GetWindowsDirectoryW Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE Windows.Win32.System.SystemInformation.SYSTEM_INFO +Windows.Win32.System.SystemServices.ALL_PROCESSOR_GROUPS Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH Windows.Win32.System.SystemServices.DLL_THREAD_DETACH Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS @@ -2514,6 +2512,7 @@ Windows.Win32.System.Threading.DeleteProcThreadAttributeList Windows.Win32.System.Threading.DETACHED_PROCESS Windows.Win32.System.Threading.ExitProcess Windows.Win32.System.Threading.EXTENDED_STARTUPINFO_PRESENT +Windows.Win32.System.Threading.GetActiveProcessorCount Windows.Win32.System.Threading.GetCurrentProcess Windows.Win32.System.Threading.GetCurrentProcessId Windows.Win32.System.Threading.GetCurrentThread @@ -2542,9 +2541,6 @@ Windows.Win32.System.Threading.PROFILE_USER Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS Windows.Win32.System.Threading.ReleaseSRWLockExclusive Windows.Win32.System.Threading.ReleaseSRWLockShared -Windows.Win32.System.Threading.RTL_CONDITION_VARIABLE -Windows.Win32.System.Threading.RTL_RUN_ONCE -Windows.Win32.System.Threading.RTL_SRWLOCK Windows.Win32.System.Threading.SetThreadStackGuarantee Windows.Win32.System.Threading.Sleep Windows.Win32.System.Threading.SleepConditionVariableSRW @@ -2584,8 +2580,6 @@ Windows.Win32.System.Threading.WaitForMultipleObjects Windows.Win32.System.Threading.WaitForSingleObject Windows.Win32.System.Threading.WakeAllConditionVariable Windows.Win32.System.Threading.WakeConditionVariable -Windows.Win32.System.WindowsProgramming.IO_STATUS_BLOCK -Windows.Win32.System.WindowsProgramming.OBJECT_ATTRIBUTES Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW // tidy-alphabetical-end diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index b24f6dc900fc5..851d15915c7d1 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -4,7 +4,7 @@ // regenerate the bindings. // // ignore-tidy-filelength -// Bindings generated by `windows-bindgen` 0.49.0 +// Bindings generated by `windows-bindgen` 0.51.1 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] #[link(name = "advapi32")] @@ -32,11 +32,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -189,18 +189,15 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn FindClose(hfindfile: FindFileHandle) -> BOOL; + pub fn FindClose(hfindfile: HANDLE) -> BOOL; } #[link(name = "kernel32")] extern "system" { - pub fn FindFirstFileW( - lpfilename: PCWSTR, - lpfindfiledata: *mut WIN32_FIND_DATAW, - ) -> FindFileHandle; + pub fn FindFirstFileW(lpfilename: PCWSTR, lpfindfiledata: *mut WIN32_FIND_DATAW) -> HANDLE; } #[link(name = "kernel32")] extern "system" { - pub fn FindNextFileW(hfindfile: FindFileHandle, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; + pub fn FindNextFileW(hfindfile: HANDLE, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; } #[link(name = "kernel32")] extern "system" { @@ -223,6 +220,10 @@ extern "system" { pub fn FreeEnvironmentStringsW(penv: PCWSTR) -> BOOL; } #[link(name = "kernel32")] +extern "system" { + pub fn GetActiveProcessorCount(groupnumber: u16) -> u32; +} +#[link(name = "kernel32")] extern "system" { pub fn GetCommandLineW() -> PCWSTR; } @@ -360,7 +361,7 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceBeginInitialize( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, fpending: *mut BOOL, lpcontext: *mut *mut ::core::ffi::c_void, @@ -369,7 +370,7 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceComplete( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, lpcontext: *const ::core::ffi::c_void, ) -> BOOL; @@ -424,7 +425,7 @@ extern "system" { extern "system" { pub fn ReadFile( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpnumberofbytesread: *mut u32, lpoverlapped: *mut OVERLAPPED, @@ -434,7 +435,7 @@ extern "system" { extern "system" { pub fn ReadFileEx( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpoverlapped: *mut OVERLAPPED, lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, @@ -442,11 +443,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -513,8 +514,8 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn SleepConditionVariableSRW( - conditionvariable: *mut RTL_CONDITION_VARIABLE, - srwlock: *mut RTL_SRWLOCK, + conditionvariable: *mut CONDITION_VARIABLE, + srwlock: *mut SRWLOCK, dwmilliseconds: u32, flags: u32, ) -> BOOL; @@ -549,11 +550,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> BOOLEAN; } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockShared(srwlock: *mut SRWLOCK) -> BOOLEAN; } #[link(name = "kernel32")] extern "system" { @@ -574,19 +575,19 @@ extern "system" { lphandles: *const HANDLE, bwaitall: BOOL, dwmilliseconds: u32, - ) -> WIN32_ERROR; + ) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR; + pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WakeAllConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeAllConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn WakeConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { @@ -847,6 +848,7 @@ impl ::core::clone::Clone for ADDRINFOA { pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16; +pub const ALL_PROCESSOR_GROUPS: u32 = 65535u32; #[repr(C)] pub union ARM64_NT_NEON128 { pub Anonymous: ARM64_NT_NEON128_0, @@ -899,7 +901,17 @@ impl ::core::clone::Clone for BY_HANDLE_FILE_INFORMATION { } pub const CALLBACK_CHUNK_FINISHED: LPPROGRESS_ROUTINE_CALLBACK_REASON = 0u32; pub const CALLBACK_STREAM_SWITCH: LPPROGRESS_ROUTINE_CALLBACK_REASON = 1u32; -pub type COMPARESTRING_RESULT = u32; +pub type COMPARESTRING_RESULT = i32; +#[repr(C)] +pub struct CONDITION_VARIABLE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for CONDITION_VARIABLE {} +impl ::core::clone::Clone for CONDITION_VARIABLE { + fn clone(&self) -> Self { + *self + } +} pub type CONSOLE_MODE = u32; #[repr(C)] pub struct CONSOLE_READCONSOLE_CONTROL { @@ -917,7 +929,7 @@ impl ::core::clone::Clone for CONSOLE_READCONSOLE_CONTROL { #[repr(C)] #[cfg(target_arch = "aarch64")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Cpsr: u32, pub Anonymous: CONTEXT_0, pub Sp: u64, @@ -1004,7 +1016,7 @@ pub struct CONTEXT { pub P4Home: u64, pub P5Home: u64, pub P6Home: u64, - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub MxCsr: u32, pub SegCs: u16, pub SegDs: u16, @@ -1100,7 +1112,7 @@ impl ::core::clone::Clone for CONTEXT_0_0 { #[repr(C)] #[cfg(target_arch = "x86")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Dr0: u32, pub Dr1: u32, pub Dr2: u32, @@ -1134,6 +1146,7 @@ impl ::core::clone::Clone for CONTEXT { *self } } +pub type CONTEXT_FLAGS = u32; pub const CP_UTF8: u32 = 65001u32; pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32; pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32; @@ -1151,9 +1164,9 @@ pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32; pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32; pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32; pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32; -pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2u32; -pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3u32; -pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1u32; +pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2i32; +pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3i32; +pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1i32; pub const DEBUG_ONLY_THIS_PROCESS: PROCESS_CREATION_FLAGS = 2u32; pub const DEBUG_PROCESS: PROCESS_CREATION_FLAGS = 1u32; pub const DELETE: FILE_ACCESS_RIGHTS = 65536u32; @@ -3369,7 +3382,6 @@ pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32; pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32; pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32; pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32; -pub type FindFileHandle = *mut ::core::ffi::c_void; pub type GENERIC_ACCESS_RIGHTS = u32; pub const GENERIC_ALL: GENERIC_ACCESS_RIGHTS = 268435456u32; pub const GENERIC_EXECUTE: GENERIC_ACCESS_RIGHTS = 536870912u32; @@ -3383,6 +3395,12 @@ pub struct GUID { pub data3: u16, pub data4: [u8; 8], } +impl ::core::marker::Copy for GUID {} +impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } +} impl GUID { pub const fn from_u128(uuid: u128) -> Self { Self { @@ -3393,12 +3411,6 @@ impl GUID { } } } -impl ::core::marker::Copy for GUID {} -impl ::core::clone::Clone for GUID { - fn clone(&self) -> Self { - *self - } -} pub type HANDLE = *mut ::core::ffi::c_void; pub type HANDLE_FLAGS = u32; pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32; @@ -3431,6 +3443,16 @@ impl ::core::clone::Clone for IN6_ADDR_0 { pub const INFINITE: u32 = 4294967295u32; pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; +#[repr(C)] +pub union INIT_ONCE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for INIT_ONCE {} +impl ::core::clone::Clone for INIT_ONCE { + fn clone(&self) -> Self { + *self + } +} pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); @@ -3659,10 +3681,10 @@ pub type NTSTATUS = i32; pub struct OBJECT_ATTRIBUTES { pub Length: u32, pub RootDirectory: HANDLE, - pub ObjectName: *mut UNICODE_STRING, + pub ObjectName: *const UNICODE_STRING, pub Attributes: u32, - pub SecurityDescriptor: *mut ::core::ffi::c_void, - pub SecurityQualityOfService: *mut ::core::ffi::c_void, + pub SecurityDescriptor: *const ::core::ffi::c_void, + pub SecurityQualityOfService: *const ::core::ffi::c_void, } impl ::core::marker::Copy for OBJECT_ATTRIBUTES {} impl ::core::clone::Clone for OBJECT_ATTRIBUTES { @@ -3712,8 +3734,8 @@ pub type PCSTR = *const u8; pub type PCWSTR = *const u16; pub type PIO_APC_ROUTINE = ::core::option::Option< unsafe extern "system" fn( - apccontext: *const ::core::ffi::c_void, - iostatusblock: *const IO_STATUS_BLOCK, + apccontext: *mut ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, reserved: u32, ) -> (), >; @@ -3755,36 +3777,6 @@ pub type PSTR = *mut u8; pub type PWSTR = *mut u16; pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; -#[repr(C)] -pub struct RTL_CONDITION_VARIABLE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_CONDITION_VARIABLE {} -impl ::core::clone::Clone for RTL_CONDITION_VARIABLE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub union RTL_RUN_ONCE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_RUN_ONCE {} -impl ::core::clone::Clone for RTL_RUN_ONCE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub struct RTL_SRWLOCK { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_SRWLOCK {} -impl ::core::clone::Clone for RTL_SRWLOCK { - fn clone(&self) -> Self { - *self - } -} pub const SD_BOTH: WINSOCK_SHUTDOWN_HOW = 2i32; pub const SD_RECEIVE: WINSOCK_SHUTDOWN_HOW = 0i32; pub const SD_SEND: WINSOCK_SHUTDOWN_HOW = 1i32; @@ -3821,10 +3813,7 @@ impl ::core::clone::Clone for SOCKADDR { *self } } -#[cfg(target_pointer_width = "32")] -pub type SOCKET = u32; -#[cfg(target_pointer_width = "64")] -pub type SOCKET = u64; +pub type SOCKET = usize; pub const SOCKET_ERROR: i32 = -1i32; pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; pub const SOCK_RAW: WINSOCK_SOCKET_TYPE = 3i32; @@ -3838,6 +3827,16 @@ pub const SO_LINGER: i32 = 128i32; pub const SO_RCVTIMEO: i32 = 4102i32; pub const SO_SNDTIMEO: i32 = 4101i32; pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; +#[repr(C)] +pub struct SRWLOCK { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for SRWLOCK {} +impl ::core::clone::Clone for SRWLOCK { + fn clone(&self) -> Self { + *self + } +} pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; @@ -4008,12 +4007,13 @@ impl ::core::clone::Clone for UNICODE_STRING { pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; -pub const WAIT_ABANDONED: WIN32_ERROR = 128u32; -pub const WAIT_ABANDONED_0: WIN32_ERROR = 128u32; -pub const WAIT_FAILED: WIN32_ERROR = 4294967295u32; -pub const WAIT_IO_COMPLETION: WIN32_ERROR = 192u32; -pub const WAIT_OBJECT_0: WIN32_ERROR = 0u32; -pub const WAIT_TIMEOUT: WIN32_ERROR = 258u32; +pub const WAIT_ABANDONED: WAIT_EVENT = 128u32; +pub const WAIT_ABANDONED_0: WAIT_EVENT = 128u32; +pub type WAIT_EVENT = u32; +pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32; +pub const WAIT_IO_COMPLETION: WAIT_EVENT = 192u32; +pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32; +pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32; pub const WC_ERR_INVALID_CHARS: u32 = 128u32; pub type WIN32_ERROR = u32; #[repr(C)] diff --git a/library/std/src/sys/windows/cmath.rs b/library/std/src/sys/windows/cmath.rs index 1b2a86f3c0eb1..36578d5a34e14 100644 --- a/library/std/src/sys/windows/cmath.rs +++ b/library/std/src/sys/windows/cmath.rs @@ -1,6 +1,6 @@ #![cfg(not(test))] -use libc::{c_double, c_float, c_int}; +use core::ffi::{c_double, c_float, c_int}; extern "C" { pub fn acos(n: c_double) -> c_double; @@ -33,7 +33,7 @@ pub use self::shims::*; #[cfg(not(all(target_env = "msvc", target_arch = "x86")))] mod shims { - use libc::c_float; + use core::ffi::c_float; extern "C" { pub fn acosf(n: c_float) -> c_float; @@ -52,7 +52,7 @@ mod shims { // back to f32. While not precisely correct should be "correct enough" for now. #[cfg(all(target_env = "msvc", target_arch = "x86"))] mod shims { - use libc::c_float; + use core::ffi::c_float; #[inline] pub unsafe fn acosf(n: c_float) -> c_float { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 21a65bc25f358..0113196b8247c 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -16,6 +16,8 @@ use crate::sys::{c, cvt, Align8}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::thread; +use core::ffi::c_void; + use super::path::maybe_verbatim; use super::to_u16s; @@ -371,7 +373,7 @@ impl File { cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), c::FileBasicInfo, - &mut info as *mut _ as *mut libc::c_void, + &mut info as *mut _ as *mut c_void, size as c::DWORD, ))?; let mut attr = FileAttr { @@ -399,7 +401,7 @@ impl File { cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), c::FileStandardInfo, - &mut info as *mut _ as *mut libc::c_void, + &mut info as *mut _ as *mut c_void, size as c::DWORD, ))?; attr.file_size = info.AllocationSize as u64; @@ -624,7 +626,7 @@ impl File { cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), c::FileBasicInfo, - &mut info as *mut _ as *mut libc::c_void, + &mut info as *mut _ as *mut c_void, size as c::DWORD, ))?; Ok(info) diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 84c1fbde32d2f..56d0d6c088737 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -143,13 +143,8 @@ impl Handle { ) -> io::Result> { let len = cmp::min(buf.len(), ::MAX as usize) as c::DWORD; let mut amt = 0; - let res = cvt(c::ReadFile( - self.as_raw_handle(), - buf.as_ptr() as c::LPVOID, - len, - &mut amt, - overlapped, - )); + let res = + cvt(c::ReadFile(self.as_raw_handle(), buf.as_mut_ptr(), len, &mut amt, overlapped)); match res { Ok(_) => Ok(Some(amt as usize)), Err(e) => { diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs index fc9856caed62f..9b540ee071f4f 100644 --- a/library/std/src/sys/windows/io.rs +++ b/library/std/src/sys/windows/io.rs @@ -3,7 +3,7 @@ use crate::mem::size_of; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle}; use crate::slice; use crate::sys::c; -use libc; +use core::ffi::c_void; #[derive(Copy, Clone)] #[repr(transparent)] @@ -136,7 +136,7 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool { let res = c::GetFileInformationByHandleEx( handle, c::FileNameInfo, - &mut name_info as *mut _ as *mut libc::c_void, + &mut name_info as *mut _ as *mut c_void, size_of::() as u32, ); if res == 0 { diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 1ae42cb7eae63..4b7115f97c500 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -15,7 +15,7 @@ use crate::sys_common::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; -use libc::{c_int, c_long, c_ulong, c_ushort}; +use core::ffi::{c_int, c_long, c_ulong, c_ushort}; pub type wrlen_t = i32; @@ -117,7 +117,7 @@ impl Socket { }; if socket != c::INVALID_SOCKET { - unsafe { Ok(Self::from_raw_socket(socket)) } + unsafe { Ok(Self::from_raw(socket)) } } else { let error = unsafe { c::WSAGetLastError() }; @@ -133,7 +133,7 @@ impl Socket { } unsafe { - let socket = Self::from_raw_socket(socket); + let socket = Self::from_raw(socket); socket.0.set_no_inherit()?; Ok(socket) } @@ -144,7 +144,7 @@ impl Socket { self.set_nonblocking(true)?; let result = { let (addr, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw_socket(), addr.as_ptr(), len) }; + let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; cvt(result).map(drop) }; self.set_nonblocking(false)?; @@ -170,7 +170,7 @@ impl Socket { let fds = { let mut fds = unsafe { mem::zeroed::() }; fds.fd_count = 1; - fds.fd_array[0] = self.as_raw_socket(); + fds.fd_array[0] = self.as_raw(); fds }; @@ -202,11 +202,11 @@ impl Socket { } pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result { - let socket = unsafe { c::accept(self.as_raw_socket(), storage, len) }; + let socket = unsafe { c::accept(self.as_raw(), storage, len) }; match socket { c::INVALID_SOCKET => Err(last_error()), - _ => unsafe { Ok(Self::from_raw_socket(socket)) }, + _ => unsafe { Ok(Self::from_raw(socket)) }, } } @@ -218,9 +218,8 @@ impl Socket { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let length = cmp::min(buf.capacity(), i32::MAX as usize) as i32; - let result = unsafe { - c::recv(self.as_raw_socket(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) - }; + let result = + unsafe { c::recv(self.as_raw(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) }; match result { c::SOCKET_ERROR => { @@ -257,7 +256,7 @@ impl Socket { let mut flags = 0; let result = unsafe { c::WSARecv( - self.as_raw_socket(), + self.as_raw(), bufs.as_mut_ptr() as *mut c::WSABUF, length, &mut nread, @@ -305,7 +304,7 @@ impl Socket { // do the same on windows to map a shut down socket to returning EOF. let result = unsafe { c::recvfrom( - self.as_raw_socket(), + self.as_raw(), buf.as_mut_ptr() as *mut _, length, flags, @@ -341,7 +340,7 @@ impl Socket { let mut nwritten = 0; let result = unsafe { c::WSASend( - self.as_raw_socket(), + self.as_raw(), bufs.as_ptr() as *const c::WSABUF as *mut _, length, &mut nwritten, @@ -392,14 +391,14 @@ impl Socket { Shutdown::Read => c::SD_RECEIVE, Shutdown::Both => c::SD_BOTH, }; - let result = unsafe { c::shutdown(self.as_raw_socket(), how) }; + let result = unsafe { c::shutdown(self.as_raw(), how) }; cvt(result).map(drop) } pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; let result = - unsafe { c::ioctlsocket(self.as_raw_socket(), c::FIONBIO as c_int, &mut nonblocking) }; + unsafe { c::ioctlsocket(self.as_raw(), c::FIONBIO as c_int, &mut nonblocking) }; cvt(result).map(drop) } @@ -433,8 +432,15 @@ impl Socket { } // This is used by sys_common code to abstract over Windows and Unix. - pub fn as_raw(&self) -> RawSocket { - self.as_inner().as_raw_socket() + pub fn as_raw(&self) -> c::SOCKET { + debug_assert_eq!(mem::size_of::(), mem::size_of::()); + debug_assert_eq!(mem::align_of::(), mem::align_of::()); + self.as_inner().as_raw_socket() as c::SOCKET + } + pub unsafe fn from_raw(raw: c::SOCKET) -> Self { + debug_assert_eq!(mem::size_of::(), mem::size_of::()); + debug_assert_eq!(mem::align_of::(), mem::align_of::()); + Self::from_raw_socket(raw as RawSocket) } } diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index d07147eccc1d3..7624e746f5c89 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -12,7 +12,7 @@ use crate::sys::c; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; use crate::sys::hashmap_random_keys; -use crate::sys_common::IntoInner; +use crate::sys_common::{FromInner, IntoInner}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -28,6 +28,12 @@ impl IntoInner for AnonPipe { } } +impl FromInner for AnonPipe { + fn from_inner(inner: Handle) -> AnonPipe { + Self { inner } + } +} + pub struct Pipes { pub ours: AnonPipe, pub theirs: AnonPipe, diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index cd5bf7f1538ca..f4078d359448e 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -19,8 +19,7 @@ use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Mutex; use crate::sys::args::{self, Arg}; -use crate::sys::c; -use crate::sys::c::NonZeroDWORD; +use crate::sys::c::{self, NonZeroDWORD, EXIT_FAILURE, EXIT_SUCCESS}; use crate::sys::cvt; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; @@ -30,7 +29,7 @@ use crate::sys::stdio; use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::sys_common::IntoInner; -use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS}; +use core::ffi::c_void; //////////////////////////////////////////////////////////////////////////////// // Command diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index 18cecb65681d2..4b825d2a9f51f 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -10,7 +10,7 @@ use crate::sys::stack_overflow; use crate::sys_common::FromInner; use crate::time::Duration; -use libc::c_void; +use core::ffi::c_void; use super::to_u16s; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index f7d821750635d..e18638f2a5f54 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -44,6 +44,7 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", + target_os = "uefi", feature = "restricted-std", all(target_family = "wasm", not(target_os = "emscripten")), target_os = "xous", diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 2976a9f578ede..4f5b17deaa2da 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -32,6 +32,7 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(any( target_os = "linux", target_os = "android", + target_os = "hurd", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku", target_os = "nto"))] { diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 18883048daef1..4d295cf0f09d5 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -80,6 +80,10 @@ impl CommandEnv { self.vars.clear(); } + pub fn does_clear(&self) -> bool { + self.clear + } + pub fn have_changed_path(&self) -> bool { self.saw_path || self.clear } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index c638cc61856fa..90ac0098dec92 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -58,6 +58,8 @@ pub use core::time::TryFromFloatSecsError; /// some seconds may be longer than others). An instant may jump forwards or /// experience time dilation (slow down or speed up), but it will never go /// backwards. +/// As part of this non-guarantee it is also not specified whether system suspends count as +/// elapsed time or not. The behavior varies across platforms and rust versions. /// /// Instants are opaque types that can only be compared to one another. There is /// no method to get "the number of seconds" from an instant. Instead, it only @@ -151,6 +153,7 @@ pub use core::time::TryFromFloatSecsError; /// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Instant")] pub struct Instant(time::Instant); /// A measurement of the system clock, useful for talking to diff --git a/library/stdarch b/library/stdarch index 6100854c4b360..333e9e9977188 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 6100854c4b360f84da5ab25e7c75cb2080667ddc +Subproject commit 333e9e9977188d0748327e9b5be0f3f412063174 diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 62e97c65569f0..94a91dd357c9f 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -145,6 +145,14 @@ extern "C" {} #[link(name = "gcc_s")] extern "C" {} +#[cfg(target_os = "aix")] +#[link(name = "unwind")] +extern "C" {} + #[cfg(target_os = "nto")] #[link(name = "gcc_s")] extern "C" {} + +#[cfg(target_os = "hurd")] +#[link(name = "gcc_s")] +extern "C" {} diff --git a/rust-bors.toml b/rust-bors.toml new file mode 100644 index 0000000000000..54f4f641248cd --- /dev/null +++ b/rust-bors.toml @@ -0,0 +1 @@ +timeout = 7200 diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md deleted file mode 100644 index 1aba0713850ae..0000000000000 --- a/src/bootstrap/CHANGELOG.md +++ /dev/null @@ -1,71 +0,0 @@ -# Changelog - -All notable changes to bootstrap will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - - -## [Changes since the last major version] - -- Vendoring is no longer done automatically when building from git sources. To use vendoring, run `cargo vendor` manually, or use the pre-vendored `rustc-src` tarball. -- `llvm-libunwind` now accepts `in-tree` (formerly true), `system` or `no` (formerly false) [#77703](https://github.com/rust-lang/rust/pull/77703) -- The options `infodir`, `localstatedir`, and `gpg-password-file` are no longer allowed in config.toml. Previously, they were ignored without warning. Note that `infodir` and `localstatedir` are still accepted by `./configure`, with a warning. [#82451](https://github.com/rust-lang/rust/pull/82451) -- Change the names for `dist` commands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684) -- The `build.fast-submodules` option has been removed. Fast submodule checkouts are enabled unconditionally. Automatic submodule handling can still be disabled with `build.submodules = false`. -- Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended. -- `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag -- `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. -- `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702) -- The `llvm.version-check` config option has been removed. Older versions were never supported. If you still need to support older versions (e.g. you are applying custom patches), patch `check_llvm_version` in bootstrap to change the minimum version. [#108619](https://github.com/rust-lang/rust/pull/108619) -- The `rust.ignore-git` option has been renamed to `rust.omit-git-hash`. [#110059](https://github.com/rust-lang/rust/pull/110059) -- `--exclude` no longer accepts a `Kind` as part of a Step; instead it uses the top-level Kind of the subcommand. If this matches how you were already using --exclude (e.g. `x test --exclude test::std`), simply remove the kind: `--exclude std`. If you were using a kind that did not match the top-level subcommand, please open an issue explaining why you wanted this feature. - -### Non-breaking changes - -- `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473) -- The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558) -- If you have Rust already installed, `x.py` will now infer the host target - from the default rust toolchain. [#78513](https://github.com/rust-lang/rust/pull/78513) -- Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false. -- Add llvm option `enable-warnings` to have control on llvm compilation warnings. Default to false. -- Add `rpath` option in `target` section to support set rpath option for each target independently. [#111242](https://github.com/rust-lang/rust/pull/111242) - - -## [Version 2] - 2020-09-25 - -- `host` now defaults to the value of `build` in all cases - + Previously `host` defaulted to an empty list when `target` was overridden, and to `build` otherwise - -### Non-breaking changes - -- Add `x.py setup` [#76631](https://github.com/rust-lang/rust/pull/76631) -- Add a changelog for x.py [#76626](https://github.com/rust-lang/rust/pull/76626) -- Optionally, download LLVM from CI on Linux and NixOS. This can be enabled with `download-ci-llvm = true` under `[llvm]`. - + [#76439](https://github.com/rust-lang/rust/pull/76349) - + [#76667](https://github.com/rust-lang/rust/pull/76667) - + [#76708](https://github.com/rust-lang/rust/pull/76708) -- Distribute rustc sources as part of `rustc-dev` [#76856](https://github.com/rust-lang/rust/pull/76856) -- Make the default stage for x.py configurable [#76625](https://github.com/rust-lang/rust/pull/76625). This can be enabled with `build-stage = N`, `doc-stage = N`, etc. -- Add a dedicated debug-logging option [#76588](https://github.com/rust-lang/rust/pull/76588). Previously, `debug-logging` could only be set with `debug-assertions`, slowing down the compiler more than necessary. -- Add sample defaults for x.py [#76628](https://github.com/rust-lang/rust/pull/76628) -- Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage - 0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed - [#77120](https://github.com/rust-lang/rust/pull/77120). -- File locking is now used to avoid collisions between multiple running instances of `x.py` (e.g. when using `rust-analyzer` and `x.py` at the same time). Note that Solaris and possibly other non Unix and non Windows systems don't support it [#108607](https://github.com/rust-lang/rust/pull/108607). This might possibly lead to build data corruption. - - -## [Version 1] - 2020-09-11 - -This is the first changelog entry, and it does not attempt to be an exhaustive list of features in x.py. -Instead, this documents the changes to bootstrap in the past 2 months. - -- Improve defaults in `x.py` [#73964](https://github.com/rust-lang/rust/pull/73964) - (see [blog post] for details) -- Set `ninja = true` by default [#74922](https://github.com/rust-lang/rust/pull/74922) -- Avoid trying to inversely cross-compile for build triple from host triples [#76415](https://github.com/rust-lang/rust/pull/76415) -- Allow blessing expect-tests in tools [#75975](https://github.com/rust-lang/rust/pull/75975) -- `x.py check` checks tests/examples/benches [#76258](https://github.com/rust-lang/rust/pull/76258) -- Fix `rust.use-lld` when linker is not set [#76326](https://github.com/rust-lang/rust/pull/76326) -- Build tests with LLD if `use-lld = true` was passed [#76378](https://github.com/rust-lang/rust/pull/76378) - -[blog post]: https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 548281ca50688..e7998a40a6520 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -181,11 +181,10 @@ Some general areas that you may be interested in modifying are: `Config` struct. * Adding a sanity check? Take a look at `bootstrap/sanity.rs`. -If you make a major change, please remember to: +If you make a major change on bootstrap configuration, please remember to: -+ Update `VERSION` in `src/bootstrap/main.rs`. -* Update `changelog-seen = N` in `config.example.toml`. -* Add an entry in `src/bootstrap/CHANGELOG.md`. ++ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs`. +* Update `change-id = {pull-request-id}` in `config.example.toml`. A 'major change' includes @@ -193,7 +192,7 @@ A 'major change' includes * A change in the default options. Changes that do not affect contributors to the compiler or users -building rustc from source don't need an update to `VERSION`. +building rustc from source don't need an update to `CONFIG_CHANGE_HISTORY`. If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs, @@ -201,3 +200,8 @@ please file issues on the [Rust issue tracker][rust-issue-tracker]. [rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap [rust-issue-tracker]: https://github.com/rust-lang/rust/issues + +## Changelog + +Because we do not release bootstrap with versions, we also do not maintain CHANGELOG files. To +review the changes made to bootstrap, simply run `git log --no-merges --oneline -- src/bootstrap`. diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index c497cabbd6922..d87fb6a9cef0c 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -13,7 +13,7 @@ use std::{env, fs}; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] use bootstrap::t; -use bootstrap::{Build, Config, Subcommand, VERSION}; +use bootstrap::{find_recent_config_change_ids, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY}; fn main() { let args = env::args().skip(1).collect::>(); @@ -42,7 +42,7 @@ fn main() { } err => { drop(err); - println!("warning: build directory locked by process {pid}, waiting for lock"); + println!("WARNING: build directory locked by process {pid}, waiting for lock"); let mut lock = t!(build_lock.write()); t!(lock.write(&process::id().to_string().as_ref())); lock @@ -51,7 +51,7 @@ fn main() { } #[cfg(any(not(any(unix, windows)), target_os = "solaris"))] - println!("warning: file locking not supported for target, not locking build directory"); + println!("WARNING: file locking not supported for target, not locking build directory"); // check_version warnings are not printed during setup let changelog_suggestion = @@ -61,7 +61,7 @@ fn main() { // changelog warning, not the `x.py setup` message. let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. }); if suggest_setup { - println!("warning: you have not made a `config.toml`"); + println!("WARNING: you have not made a `config.toml`"); println!( "help: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" @@ -74,7 +74,7 @@ fn main() { Build::new(config).build(); if suggest_setup { - println!("warning: you have not made a `config.toml`"); + println!("WARNING: you have not made a `config.toml`"); println!( "help: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" @@ -91,7 +91,7 @@ fn main() { contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570") }) { println!( - "warning: You have the pre-push script installed to .git/hooks/pre-commit. \ + "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \ Consider moving it to .git/hooks/pre-push instead, which runs less often." ); } @@ -104,19 +104,34 @@ fn main() { fn check_version(config: &Config) -> Option { let mut msg = String::new(); - let suggestion = if let Some(seen) = config.changelog_seen { - if seen != VERSION { - msg.push_str("warning: there have been changes to x.py since you last updated.\n"); - format!("update `config.toml` to use `changelog-seen = {VERSION}` instead") + if config.changelog_seen.is_some() { + msg.push_str("WARNING: The use of `changelog-seen` is deprecated. Please refer to `change-id` option in `config.example.toml` instead.\n"); + } + + let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); + let suggestion = if let Some(id) = config.change_id { + if &id != latest_config_id { + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); + let change_links: Vec = find_recent_config_change_ids(id) + .iter() + .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) + .collect(); + if !change_links.is_empty() { + msg.push_str("To see more detail about these changes, visit the following PRs:\n"); + for link in change_links { + msg.push_str(&format!(" - {link}\n")); + } + } + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); + format!("update `config.toml` to use `change-id = {latest_config_id}` instead") } else { return None; } } else { - msg.push_str("warning: x.py has made several changes recently you may want to look at\n"); - format!("add `changelog-seen = {VERSION}` at the top of `config.toml`") + msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); + format!("add `change-id = {latest_config_id}` at the top of `config.toml`") }; - msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n"); msg.push_str("note: to silence this warning, "); msg.push_str(&suggestion); diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index a9aa7524e8bc7..1a1125a107fe1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -41,6 +41,10 @@ def get_cpus(): return 1 +def eprint(*args, **kwargs): + kwargs["file"] = sys.stderr + print(*args, **kwargs) + def get(base, url, path, checksums, verbose=False): with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -57,23 +61,23 @@ def get(base, url, path, checksums, verbose=False): if os.path.exists(path): if verify(path, sha256, False): if verbose: - print("using already-download file", path, file=sys.stderr) + eprint("using already-download file", path) return else: if verbose: - print("ignoring already-download file", - path, "due to failed verification", file=sys.stderr) + eprint("ignoring already-download file", + path, "due to failed verification") os.unlink(path) download(temp_path, "{}/{}".format(base, url), True, verbose) if not verify(temp_path, sha256, verbose): raise RuntimeError("failed verification") if verbose: - print("moving {} to {}".format(temp_path, path), file=sys.stderr) + eprint("moving {} to {}".format(temp_path, path)) shutil.move(temp_path, path) finally: if os.path.isfile(temp_path): if verbose: - print("removing", temp_path, file=sys.stderr) + eprint("removing", temp_path) os.unlink(temp_path) @@ -83,7 +87,7 @@ def download(path, url, probably_big, verbose): _download(path, url, probably_big, verbose, True) return except RuntimeError: - print("\nspurious failure, trying again", file=sys.stderr) + eprint("\nspurious failure, trying again") _download(path, url, probably_big, verbose, False) @@ -94,7 +98,7 @@ def _download(path, url, probably_big, verbose, exception): # - If we are on win32 fallback to powershell # - Otherwise raise the error if appropriate if probably_big or verbose: - print("downloading {}".format(url), file=sys.stderr) + eprint("downloading {}".format(url)) try: if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ: @@ -129,20 +133,20 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, expected, verbose): """Check if the sha256 sum of the given path is valid""" if verbose: - print("verifying", path, file=sys.stderr) + eprint("verifying", path) with open(path, "rb") as source: found = hashlib.sha256(source.read()).hexdigest() verified = found == expected if not verified: - print("invalid checksum:\n" + eprint("invalid checksum:\n" " found: {}\n" - " expected: {}".format(found, expected), file=sys.stderr) + " expected: {}".format(found, expected)) return verified def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): """Unpack the given tarball file""" - print("extracting", tarball, file=sys.stderr) + eprint("extracting", tarball) fname = os.path.basename(tarball).replace(tarball_suffix, "") with contextlib.closing(tarfile.open(tarball)) as tar: for member in tar.getnames(): @@ -155,7 +159,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): dst_path = os.path.join(dst, name) if verbose: - print(" extracting", member, file=sys.stderr) + eprint(" extracting", member) tar.extract(member, dst) src_path = os.path.join(dst, member) if os.path.isdir(src_path) and os.path.exists(dst_path): @@ -167,7 +171,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: - print("running: " + ' '.join(args), file=sys.stderr) + eprint("running: " + ' '.join(args)) sys.stdout.flush() # Ensure that the .exe is used on Windows just in case a Linux ELF has been # compiled in the same directory. @@ -207,8 +211,8 @@ def require(cmd, exit=True, exception=False): if exception: raise elif exit: - print("error: unable to run `{}`: {}".format(' '.join(cmd), exc), file=sys.stderr) - print("Please make sure it's installed and in the path.", file=sys.stderr) + eprint("error: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("Please make sure it's installed and in the path.") sys.exit(1) return None @@ -239,14 +243,12 @@ def default_build_triple(verbose): host = next(x for x in version.split('\n') if x.startswith("host: ")) triple = host.split("host: ")[1] if verbose: - print("detected default triple {} from pre-installed rustc".format(triple), - file=sys.stderr) + eprint("detected default triple {} from pre-installed rustc".format(triple)) return triple except Exception as e: if verbose: - print("pre-installed rustc not detected: {}".format(e), - file=sys.stderr) - print("falling back to auto-detect", file=sys.stderr) + eprint("pre-installed rustc not detected: {}".format(e)) + eprint("falling back to auto-detect") required = not platform_is_win32() uname = require(["uname", "-smp"], exit=required) @@ -265,7 +267,8 @@ def default_build_triple(verbose): 'FreeBSD': 'unknown-freebsd', 'Haiku': 'unknown-haiku', 'NetBSD': 'unknown-netbsd', - 'OpenBSD': 'unknown-openbsd' + 'OpenBSD': 'unknown-openbsd', + 'GNU': 'unknown-hurd', } # Consider the direct transformation first and then the special cases @@ -336,6 +339,7 @@ def default_build_triple(verbose): 'i386': 'i686', 'i486': 'i686', 'i686': 'i686', + 'i686-AT386': 'i686', 'i786': 'i686', 'loongarch64': 'loongarch64', 'm68k': 'm68k', @@ -670,15 +674,14 @@ def get_answer(): if not is_nixos: in_nix_shell = os.getenv('IN_NIX_SHELL') if in_nix_shell: - print("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), - "you may need to set `patch-binaries-for-nix=true` in config.toml", - file=sys.stderr) + eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), + "you may need to set `patch-binaries-for-nix=true` in config.toml") return is_nixos answer = self._should_fix_bins_and_dylibs = get_answer() if answer: - print("info: You seem to be using Nix.", file=sys.stderr) + eprint("info: You seem to be using Nix.") return answer def fix_bin_or_dylib(self, fname): @@ -691,7 +694,7 @@ def fix_bin_or_dylib(self, fname): Please see https://nixos.org/patchelf.html for more information """ assert self._should_fix_bins_and_dylibs is True - print("attempting to patch", fname, file=sys.stderr) + eprint("attempting to patch", fname) # Only build `.nix-deps` once. nix_deps_dir = self.nix_deps_dir @@ -724,7 +727,7 @@ def fix_bin_or_dylib(self, fname): "nix-build", "-E", nix_expr, "-o", nix_deps_dir, ]) except subprocess.CalledProcessError as reason: - print("warning: failed to call nix-build:", reason, file=sys.stderr) + eprint("warning: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir @@ -744,7 +747,7 @@ def fix_bin_or_dylib(self, fname): try: subprocess.check_output([patchelf] + patchelf_args + [fname]) except subprocess.CalledProcessError as reason: - print("warning: failed to call patchelf:", reason, file=sys.stderr) + eprint("warning: failed to call patchelf:", reason) return def rustc_stamp(self): @@ -886,7 +889,7 @@ def build_bootstrap(self): if "GITHUB_ACTIONS" in env: print("::group::Building bootstrap") else: - print("Building bootstrap", file=sys.stderr) + eprint("Building bootstrap") args = self.build_bootstrap_cmd(env) # Run this from the source directory so cargo finds .cargo/config @@ -951,6 +954,13 @@ def build_bootstrap_cmd(self, env): if deny_warnings: env["RUSTFLAGS"] += " -Dwarnings" + # Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation. + # Note that RUSTFLAGS_BOOTSTRAP should always be added to the end of + # RUSTFLAGS to be actually effective (e.g., if we have `-Dwarnings` in + # RUSTFLAGS, passing `-Awarnings` from RUSTFLAGS_BOOTSTRAP should override it). + if "RUSTFLAGS_BOOTSTRAP" in env: + env["RUSTFLAGS"] += " " + env["RUSTFLAGS_BOOTSTRAP"] + env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): @@ -995,12 +1005,9 @@ def check_vendored_status(self): if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - print('info: looks like you\'re trying to run this command as root', - file=sys.stderr) - print(' and so in order to preserve your $HOME this will now', - file=sys.stderr) - print(' use vendored sources by default.', - file=sys.stderr) + eprint('info: looks like you\'re trying to run this command as root') + eprint(' and so in order to preserve your $HOME this will now') + eprint(' use vendored sources by default.') cargo_dir = os.path.join(self.rust_root, '.cargo') if self.use_vendored_sources: @@ -1010,18 +1017,14 @@ def check_vendored_status(self): "--sync ./src/tools/rust-analyzer/Cargo.toml " \ "--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \ "--sync ./src/bootstrap/Cargo.toml " - print('error: vendoring required, but vendor directory does not exist.', - file=sys.stderr) - print(' Run `cargo vendor {}` to initialize the ' - 'vendor directory.'.format(sync_dirs), - file=sys.stderr) - print('Alternatively, use the pre-vendored `rustc-src` dist component.', - file=sys.stderr) + eprint('error: vendoring required, but vendor directory does not exist.') + eprint(' Run `cargo vendor {}` to initialize the ' + 'vendor directory.'.format(sync_dirs)) + eprint('Alternatively, use the pre-vendored `rustc-src` dist component.') raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - print('error: vendoring required, but .cargo/config does not exist.', - file=sys.stderr) + eprint('error: vendoring required, but .cargo/config does not exist.') raise Exception("{} not found".format(cargo_dir)) else: if os.path.exists(cargo_dir): @@ -1046,6 +1049,12 @@ def bootstrap(args): """Configure, fetch, build and run the initial bootstrap""" rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + if not os.path.exists(os.path.join(rust_root, '.git')) and \ + os.path.exists(os.path.join(rust_root, '.github')): + eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a " + "git clone nor distributed tarball.\nThis build may fail due to missing submodules " + "unless you put them in place manually.") + # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, # then `config.toml` in the root directory. toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG') @@ -1115,10 +1124,9 @@ def main(): # If the user is asking for help, let them know that the whole download-and-build # process has to happen before anything is printed out. if help_triggered: - print( + eprint( "info: Downloading and building bootstrap before processing --help command.\n" - " See src/bootstrap/README.md for help with common commands." - , file=sys.stderr) + " See src/bootstrap/README.md for help with common commands.") exit_code = 0 success_word = "successfully" @@ -1129,12 +1137,11 @@ def main(): exit_code = error.code else: exit_code = 1 - print(error, file=sys.stderr) + eprint(error) success_word = "unsuccessfully" if not help_triggered: - print("Build completed", success_word, "in", format_build_time(time() - start_time), - file=sys.stderr) + eprint("Build completed", success_word, "in", format_build_time(time() - start_time)) sys.exit(exit_code) diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index dc06a4c97343d..fefd6b187394a 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -103,7 +103,7 @@ class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" def test_no_args(self): build = serialize_and_parse([]) - self.assertEqual(build.get_toml("changelog-seen"), '2') + self.assertEqual(build.get_toml("change-id"), '115898') self.assertEqual(build.get_toml("profile"), 'dist') self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4f19ffa83dbe8..6821ded1458bd 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -158,6 +158,25 @@ impl Step for Std { target_deps.extend(copy_third_party_objects(builder, &compiler, target)); target_deps.extend(copy_self_contained_objects(builder, &compiler, target)); + // The LLD wrappers and `rust-lld` are self-contained linking components that can be + // necessary to link the stdlib on some targets. We'll also need to copy these binaries to + // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target. + if compiler.stage == 0 && compiler.host == builder.config.build { + // We want to copy the host `bin` folder within the `rustlib` folder in the sysroot. + let src_sysroot_bin = builder + .rustc_snapshot_sysroot() + .join("lib") + .join("rustlib") + .join(compiler.host.triple) + .join("bin"); + if src_sysroot_bin.exists() { + let target_sysroot_bin = + builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin"); + t!(fs::create_dir_all(&target_sysroot_bin)); + builder.cp_r(&src_sysroot_bin, &target_sysroot_bin); + } + } + let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build"); std_cargo(builder, target, compiler.stage, &mut cargo); for krate in &*self.crates { @@ -1658,15 +1677,17 @@ impl Step for Assemble { let src_exe = exe("lld", target_compiler.host); let dst_exe = exe("rust-lld", target_compiler.host); builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe)); - // for `-Z gcc-ld=lld` - let gcc_ld_dir = libdir_bin.join("gcc-ld"); - t!(fs::create_dir(&gcc_ld_dir)); + let self_contained_lld_dir = libdir_bin.join("gcc-ld"); + t!(fs::create_dir(&self_contained_lld_dir)); let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper { compiler: build_compiler, target: target_compiler.host, }); for name in crate::LLD_FILE_NAMES { - builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host))); + builder.copy( + &lld_wrapper_exe, + &self_contained_lld_dir.join(exe(name, target_compiler.host)), + ); } } @@ -1789,7 +1810,10 @@ pub fn run_cargo( // During check builds we need to keep crate metadata keep = true; } else if rlib_only_metadata { - if filename.contains("jemalloc_sys") || filename.contains("rustc_smir") { + if filename.contains("jemalloc_sys") + || filename.contains("rustc_smir") + || filename.contains("stable_mir") + { // jemalloc_sys and rustc_smir are not linked into librustc_driver.so, // so we need to distribute them as rlib to be able to use them. keep |= filename.ends_with(".rlib"); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 176ef8e92dbec..1755c3166def8 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -112,7 +112,8 @@ impl Display for DebuginfoLevel { /// `config.example.toml`. #[derive(Default, Clone)] pub struct Config { - pub changelog_seen: Option, + pub changelog_seen: Option, // FIXME: Deprecated field. Remove it at 2024. + pub change_id: Option, pub ccache: Option, /// Call Build::ninja() instead of this. pub ninja_in_file: bool, @@ -532,11 +533,7 @@ pub struct Target { impl Target { pub fn from_triple(triple: &str) -> Self { let mut target: Self = Default::default(); - if triple.contains("-none") - || triple.contains("nvptx") - || triple.contains("switch") - || triple.contains("-uefi") - { + if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") { target.no_std = true; } target @@ -550,7 +547,8 @@ impl Target { #[derive(Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct TomlConfig { - changelog_seen: Option, + changelog_seen: Option, // FIXME: Deprecated field. Remove it at 2024. + change_id: Option, build: Option, install: Option, llvm: Option, @@ -578,7 +576,17 @@ trait Merge { impl Merge for TomlConfig { fn merge( &mut self, - TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self, + TomlConfig { + build, + install, + llvm, + rust, + dist, + target, + profile: _, + changelog_seen, + change_id, + }: Self, replace: ReplaceOpt, ) { fn do_merge(x: &mut Option, y: Option, replace: ReplaceOpt) { @@ -591,6 +599,7 @@ impl Merge for TomlConfig { } } self.changelog_seen.merge(changelog_seen, replace); + self.change_id.merge(change_id, replace); do_merge(&mut self.build, build, replace); do_merge(&mut self.install, install, replace); do_merge(&mut self.llvm, llvm, replace); @@ -1246,6 +1255,7 @@ impl Config { toml.merge(override_toml, ReplaceOpt::Override); config.changelog_seen = toml.changelog_seen; + config.change_id = toml.change_id; let build = toml.build.unwrap_or_default(); if let Some(file_build) = build.build { diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index aac76cdcbcf84..d091f33eee44d 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -102,7 +102,7 @@ fn override_toml() { &[ "check".to_owned(), "--config=/does/not/exist".to_owned(), - "--set=changelog-seen=1".to_owned(), + "--set=change-id=1".to_owned(), "--set=rust.lto=fat".to_owned(), "--set=rust.deny-warnings=false".to_owned(), "--set=build.gdb=\"bar\"".to_owned(), @@ -112,7 +112,7 @@ fn override_toml() { |&_| { toml::from_str( r#" -changelog-seen = 0 +change-id = 0 [rust] lto = "off" deny-warnings = true @@ -129,7 +129,7 @@ build-config = {} .unwrap() }, ); - assert_eq!(config.changelog_seen, Some(1), "setting top-level value"); + assert_eq!(config.change_id, Some(1), "setting top-level value"); assert_eq!( config.rust_lto, crate::config::RustcLto::Fat, @@ -156,10 +156,10 @@ fn override_toml_duplicate() { &[ "check".to_owned(), "--config=/does/not/exist".to_owned(), - "--set=changelog-seen=1".to_owned(), - "--set=changelog-seen=2".to_owned(), + "--set=change-id=1".to_owned(), + "--set=change-id=2".to_owned(), ], - |&_| toml::from_str("changelog-seen = 0").unwrap(), + |&_| toml::from_str("change-id = 0").unwrap(), ); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 32da4ac29a463..05556d2f67909 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -471,14 +471,15 @@ impl Step for Rustc { let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); let rust_lld = exe("rust-lld", compiler.host); builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); - // for `-Z gcc-ld=lld` - let gcc_lld_src_dir = src_dir.join("gcc-ld"); - let gcc_lld_dst_dir = dst_dir.join("gcc-ld"); - t!(fs::create_dir(&gcc_lld_dst_dir)); + let self_contained_lld_src_dir = src_dir.join("gcc-ld"); + let self_contained_lld_dst_dir = dst_dir.join("gcc-ld"); + t!(fs::create_dir(&self_contained_lld_dst_dir)); for name in crate::LLD_FILE_NAMES { let exe_name = exe(name, compiler.host); - builder - .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name)); + builder.copy( + &self_contained_lld_src_dir.join(&exe_name), + &self_contained_lld_dst_dir.join(&exe_name), + ); } } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index b62aa9992469b..885b3a782367f 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -45,6 +45,23 @@ fn sanitize_sh(path: &Path) -> String { } } +fn is_dir_writable_for_user(dir: &PathBuf) -> bool { + let tmp = dir.join(".tmp"); + match fs::create_dir_all(&tmp) { + Ok(_) => { + fs::remove_dir_all(tmp).unwrap(); + true + } + Err(e) => { + if e.kind() == std::io::ErrorKind::PermissionDenied { + false + } else { + panic!("Failed the write access check for the current user. {}", e); + } + } + } +} + fn install_sh( builder: &Builder<'_>, package: &str, @@ -56,6 +73,17 @@ fn install_sh( let prefix = default_path(&builder.config.prefix, "/usr/local"); let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); + + // Sanity check for the user write access on prefix and sysconfdir + assert!( + is_dir_writable_for_user(&prefix), + "User doesn't have write access on `install.prefix` path in the `config.toml`.", + ); + assert!( + is_dir_writable_for_user(&sysconfdir), + "User doesn't have write access on `install.sysconfdir` path in `config.toml`." + ); + let datadir = prefix.join(default_path(&builder.config.datadir, "share")); let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust")); let mandir = prefix.join(default_path(&builder.config.mandir, "share/man")); @@ -92,6 +120,9 @@ fn prepare_dir(mut path: PathBuf) -> String { // More information on the environment variable is available here: // https://www.gnu.org/prep/standards/html_node/DESTDIR.html if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) { + // Sanity check for the user write access on DESTDIR + assert!(is_dir_writable_for_user(&destdir), "User doesn't have write access on DESTDIR."); + let without_destdir = path.clone(); path = destdir; // Custom .join() which ignores disk roots. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 1e001fae8ab43..5c78015e56089 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -112,7 +112,15 @@ const LLVM_TOOLS: &[&str] = &[ /// LLD file names for all flavors. const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; -pub const VERSION: usize = 2; +/// Keeps track of major changes made to the bootstrap configuration. +/// +/// These values also represent the IDs of the PRs that caused major changes. +/// You can visit `https://github.com/rust-lang/rust/pull/{any-id-from-the-list}` to +/// check for more details regarding each change. +/// +/// If you make any major changes (such as adding new values or changing default values), please +/// ensure that the associated PR ID is added to the end of this list. +pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898]; /// Extra --check-cfg to add when building /// (Mode restriction, config name, config values (if any)) @@ -133,7 +141,9 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ // #[cfg(bootstrap)] (Some(Mode::Std), "target_vendor", Some(&["unikraft"])), (Some(Mode::Std), "target_env", Some(&["libnx"])), - (Some(Mode::Std), "target_os", Some(&["teeos"])), + // #[cfg(bootstrap)] hurd + (Some(Mode::Std), "target_os", Some(&["teeos", "hurd"])), + (Some(Mode::Rustc), "target_os", Some(&["hurd"])), // #[cfg(bootstrap)] mips32r6, mips64r6 ( Some(Mode::Std), @@ -1842,3 +1852,16 @@ fn envify(s: &str) -> String { .flat_map(|c| c.to_uppercase()) .collect() } + +pub fn find_recent_config_change_ids(current_id: usize) -> Vec { + let index = CONFIG_CHANGE_HISTORY + .iter() + .position(|&id| id == current_id) + .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id)); + + CONFIG_CHANGE_HISTORY + .iter() + .skip(index + 1) // Skip the current_id and IDs before it + .cloned() + .collect() +} diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 7e5ade50ca76c..4556831589bd7 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -703,14 +703,7 @@ fn configure_cmake( cflags.push(" "); cflags.push(s); } - // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10. - if target.contains("apple-ios") { - if target.contains("86-") { - cflags.push(" -miphonesimulator-version-min=10.0"); - } else { - cflags.push(" -miphoneos-version-min=10.0"); - } - } + if builder.config.llvm_clang_cl.is_some() { cflags.push(&format!(" --target={target}")); } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index a9865e262fece..0b67079917c7f 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -6,6 +6,13 @@ Q := @ BOOTSTRAP_ARGS := endif +# Pass `-jN` to the bootstrap if it is specified. +ifdef MAKEFLAGS + ifneq (,$(findstring -j, $(MAKEFLAGS))) + BOOTSTRAP_ARGS += $(filter -j%, $(MAKEFLAGS)) + endif +endif + BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py all: diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index ef0234957b585..14ec33147fb9f 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -1,6 +1,6 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::Config; -use crate::{t, VERSION}; +use crate::{t, CONFIG_CHANGE_HISTORY}; use sha2::Digest; use std::env::consts::EXE_SUFFIX; use std::fmt::Write as _; @@ -208,10 +208,11 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { crate::exit!(1); } + let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap(); let settings = format!( "# Includes one of the default files in src/bootstrap/defaults\n\ profile = \"{profile}\"\n\ - changelog-seen = {VERSION}\n" + change-id = {latest_change_id}\n" ); t!(fs::write(path, settings)); diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index b83b198780ba7..2e64568371306 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -271,7 +271,7 @@ For targets: `loongarch64-unknown-linux-gnu` - Operating System > Linux kernel version = 5.19.16 - Binary utilities > Version of binutils = 2.40 - C-library > glibc version = 2.36 -- C compiler > gcc version = 13.1.0 +- C compiler > gcc version = 13.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `mips-linux-gnu.defconfig` @@ -407,7 +407,7 @@ For targets: `riscv64-unknown-linux-gnu` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 4.20.17 -- Binary utilities > Version of binutils = 2.32 +- Binary utilities > Version of binutils = 2.36.1 - C-library > glibc version = 2.29 - C compiler > gcc version = 8.5.0 - C compiler > C++ = ENABLE -- to cross compile LLVM diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 78689c429c2e3..55c737bd0aa31 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -3,9 +3,8 @@ FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -# The latest released version does not support LoongArch. -COPY scripts/crosstool-ng-git.sh /scripts/ -RUN sh /scripts/crosstool-ng-git.sh +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 8f4ad0f4e755c..3372baed999ac 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -29,8 +29,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ g++-arm-linux-gnueabi \ g++-arm-linux-gnueabihf \ g++-aarch64-linux-gnu \ - g++-mips64-linux-gnuabi64 \ - g++-mips64el-linux-gnuabi64 \ gcc-arm-none-eabi \ gcc-sparc64-linux-gnu \ libc6-dev-sparc64-cross \ @@ -48,12 +46,6 @@ WORKDIR /build COPY host-x86_64/dist-various-1/install-x86_64-redox.sh /build RUN ./install-x86_64-redox.sh -COPY host-x86_64/dist-various-1/install-mips-musl.sh /build -RUN ./install-mips-musl.sh - -COPY host-x86_64/dist-various-1/install-mipsel-musl.sh /build -RUN ./install-mipsel-musl.sh - COPY host-x86_64/dist-various-1/install-aarch64-none-elf.sh /build RUN ./install-aarch64-none-elf.sh @@ -76,32 +68,7 @@ RUN env \ env \ CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a+fp" \ CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a+fp" \ - bash musl.sh armv7hf && \ - env \ - CC=mips-openwrt-linux-gcc \ - CXX=mips-openwrt-linux-g++ \ - bash musl.sh mips && \ - env \ - CC=mipsel-openwrt-linux-gcc \ - CXX=mipsel-openwrt-linux-g++ \ - bash musl.sh mipsel && \ - env \ - CC=mips64-linux-gnuabi64-gcc \ - CXX=mips64-linux-gnuabi64-g++ \ - bash musl.sh mips64 && \ - env \ - CC=mips64el-linux-gnuabi64-gcc \ - CXX=mips64el-linux-gnuabi64-g++ \ - bash musl.sh mips64el && \ - rm -rf /build/* - -# FIXME(mozilla/sccache#235) this shouldn't be necessary but is currently -# necessary to disambiguate the mips compiler with the mipsel compiler. We want -# to give these two wrapper scripts (currently identical ones) different hashes -# to ensure that sccache understands that they're different compilers. -RUN \ - echo "# a" >> /usr/local/mips-linux-musl/bin/mips-openwrt-linux-musl-wrapper.sh && \ - echo "# b" >> /usr/local/mipsel-linux-musl/bin/mipsel-openwrt-linux-musl-wrapper.sh + bash musl.sh armv7hf ENV RUN_MAKE_TARGETS=thumbv6m-none-eabi ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7m-none-eabi @@ -110,10 +77,6 @@ ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7em-none-eabihf ENV TARGETS=asmjs-unknown-emscripten ENV TARGETS=$TARGETS,wasm32-unknown-emscripten -ENV TARGETS=$TARGETS,mips-unknown-linux-musl -ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl -ENV TARGETS=$TARGETS,mips64-unknown-linux-muslabi64 -ENV TARGETS=$TARGETS,mips64el-unknown-linux-muslabi64 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi @@ -149,10 +112,6 @@ ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft CFLAGS_arm_unknown_linux_musleabi="-march=armv6 -marm" \ CFLAGS_arm_unknown_linux_musleabihf="-march=armv6 -marm -mfpu=vfp" \ CFLAGS_armv7_unknown_linux_musleabihf="-march=armv7-a+fp" \ - CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ - CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ - CC_mips64el_unknown_linux_muslabi64=mips64el-linux-gnuabi64-gcc \ - CC_mips64_unknown_linux_muslabi64=mips64-linux-gnuabi64-gcc \ CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ @@ -177,10 +136,6 @@ ENV RUST_CONFIGURE_ARGS \ --musl-root-arm=/musl-arm \ --musl-root-armhf=/musl-armhf \ --musl-root-armv7hf=/musl-armv7hf \ - --musl-root-mips=/musl-mips \ - --musl-root-mipsel=/musl-mipsel \ - --musl-root-mips64=/musl-mips64 \ - --musl-root-mips64el=/musl-mips64el \ --disable-docs ENV SCRIPT \ diff --git a/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh b/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh deleted file mode 100755 index abab18093469c..0000000000000 --- a/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -set -ex - -mkdir /usr/local/mips-linux-musl - -# originally from -# https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/ -# OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 -URL="https://ci-mirrors.rust-lang.org/rustc" -FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2" -curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2 - -for file in /usr/local/mips-linux-musl/bin/mips-openwrt-linux-*; do - ln -s $file /usr/local/bin/`basename $file` -done diff --git a/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh deleted file mode 100755 index 779acb2d84116..0000000000000 --- a/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -set -ex - -mkdir /usr/local/mipsel-linux-musl - -# Note that this originally came from: -# https://downloads.openwrt.org/snapshots/trunk/malta/generic/ -# OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 -URL="https://ci-mirrors.rust-lang.org/rustc" -FILE="OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2" -curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2 - -for file in /usr/local/mipsel-linux-musl/bin/mipsel-openwrt-linux-*; do - ln -s $file /usr/local/bin/`basename $file` -done diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 670e37b9d01a7..01b46118b9c1e 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -128,6 +128,8 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd ENV TARGETS=$TARGETS,x86_64-unknown-none +ENV TARGETS=$TARGETS,loongarch64-unknown-none +ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi 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 6f1b2a6a638be..c04121a8bee6d 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 @@ -84,7 +84,8 @@ ENV RUST_CONFIGURE_ARGS \ --set llvm.ninja=false \ --set rust.jemalloc \ --set rust.use-lld=true \ - --set rust.lto=thin + --set rust.lto=thin \ + --set rust.codegen-units=1 ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 02b023fe75bf6..56ee348a337ec 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-17.0.0-rc3 +LLVM=llvmorg-17.0.2 mkdir llvm-project cd llvm-project diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile deleted file mode 100644 index 0d0f1edd003cb..0000000000000 --- a/src/ci/docker/host-x86_64/wasm32/Dockerfile +++ /dev/null @@ -1,63 +0,0 @@ -FROM ubuntu:22.04 - -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - libssl-dev \ - bzip2 \ - && rm -rf /var/lib/apt/lists/* - -COPY scripts/emscripten.sh /scripts/ -RUN bash /scripts/emscripten.sh - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -# emcc seems to need python to specifically be "python" and not "python3" -RUN ln `which python3` /usr/bin/python - -ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ - -# Rust's build system requires NodeJS to be in the path, but the directory in -# which emsdk stores it contains the version number. This caused breakages in -# the past when emsdk bumped the node version causing the path to point to a -# missing directory. -# -# To avoid the problem this symlinks the latest NodeJs version available to -# "latest", and adds that to the path. -RUN ln -s /emsdk-portable/node/$(ls /emsdk-portable/node | sort -V | tail -n 1) \ - /emsdk-portable/node/latest -ENV PATH=$PATH:/emsdk-portable/node/latest/bin/ - -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ -ENV EMSDK=/emsdk-portable -ENV EM_CONFIG=/emsdk-portable/.emscripten -ENV EM_CACHE=/emsdk-portable/upstream/emscripten/cache - -ENV TARGETS=wasm32-unknown-emscripten - -# Use -O1 optimizations in the link step to reduce time spent optimizing. -ENV EMCC_CFLAGS=-O1 - -COPY static/gitconfig /etc/gitconfig - -# Emscripten installation is user-specific -ENV NO_CHANGE_USER=1 -RUN chown 10719 -R /emsdk-portable/ - -# Exclude library/alloc due to OOM in benches. -# FIXME: Fix std tests -ENV SCRIPT python3 ../x.py test --stage 2 --host='' --target $TARGETS \ - --skip library/alloc --skip library/std diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index e9c155b137836..22aabda2bb34b 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -264,6 +264,9 @@ else BASE_COMMIT="" fi +SUMMARY_FILE=github-summary.md +touch $objdir/${SUMMARY_FILE} + docker \ run \ --workdir /checkout/obj \ @@ -275,6 +278,7 @@ docker \ --env CI \ --env GITHUB_ACTIONS \ --env GITHUB_REF \ + --env GITHUB_STEP_SUMMARY="/checkout/obj/${SUMMARY_FILE}" \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env TOOLSTATE_REPO \ --env TOOLSTATE_PUBLISH \ @@ -289,6 +293,8 @@ docker \ rust-ci \ $command +cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" + if [ -f /.dockerenv ]; then rm -rf $objdir docker cp checkout:/checkout/obj $objdir diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh deleted file mode 100644 index b8d3991532717..0000000000000 --- a/src/ci/docker/scripts/crosstool-ng-git.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -set -ex - -URL=https://github.com/crosstool-ng/crosstool-ng -REV=227d99d7f3115f3a078595a580d2b307dcd23e93 - -mkdir crosstool-ng -cd crosstool-ng -git init -git fetch --depth=1 ${URL} ${REV} -git reset --hard FETCH_HEAD -./bootstrap -./configure --prefix=/usr/local -make -j$(nproc) -make install -cd .. -rm -rf crosstool-ng diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh index a28d7bde2accf..c3ee19b8d2c1f 100644 --- a/src/ci/docker/scripts/crosstool-ng.sh +++ b/src/ci/docker/scripts/crosstool-ng.sh @@ -1,7 +1,7 @@ #!/bin/sh set -ex -CT_NG=1.25.0 +CT_NG=1.26.0 url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-$CT_NG.tar.gz" curl -Lf $url | tar xzf - diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 973b9a0a089b8..93b07350ac172 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -281,6 +281,7 @@ on: - auto - try - try-perf + - automation/bors/try - master pull_request: branches: @@ -427,9 +428,6 @@ jobs: - name: test-various <<: *job-linux-8c - - name: wasm32 - <<: *job-linux-8c - - name: x86_64-gnu <<: *job-linux-4c @@ -484,7 +482,7 @@ jobs: SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 @@ -497,7 +495,7 @@ jobs: SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 @@ -509,8 +507,8 @@ jobs: SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + MACOSX_DEPLOYMENT_TARGET: 10.12 + MACOSX_STD_DEPLOYMENT_TARGET: 10.12 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -691,7 +689,7 @@ jobs: env: DIST_TRY_BUILD: 1 <<: [*shared-ci-variables, *prod-variables] - if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust' + if: github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust')) strategy: matrix: include: diff --git a/src/ci/run.sh b/src/ci/run.sh index 98f2cdac5dc75..abeff7b837dcd 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -47,7 +47,8 @@ source "$ci_dir/shared.sh" export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse -if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then +if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \ + isCiBranch automation/bors/try; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" HAS_METRICS=1 diff --git a/src/ci/scripts/setup-environment.sh b/src/ci/scripts/setup-environment.sh index 0bc35f932832c..d3c55a4d6b4aa 100755 --- a/src/ci/scripts/setup-environment.sh +++ b/src/ci/scripts/setup-environment.sh @@ -10,7 +10,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # Load extra environment variables vars="${EXTRA_VARIABLES-}" -echo "${vars}" | jq '' >/dev/null # Validate JSON and exit on errors +echo "${vars}" | jq '.' >/dev/null # Validate JSON and exit on errors for key in $(echo "${vars}" | jq "keys[]" -r); do # On Windows, for whatever reason, $key contains the BOM character in it, # and that messes up `jq ".${key}"`. This line strips the BOM from the key. diff --git a/src/ci/scripts/verify-channel.sh b/src/ci/scripts/verify-channel.sh index cd28748a44b32..edeea20144be3 100755 --- a/src/ci/scripts/verify-channel.sh +++ b/src/ci/scripts/verify-channel.sh @@ -8,7 +8,7 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if isCiBranch auto || isCiBranch try || isCiBranch try-perf; then +if isCiBranch auto || isCiBranch try || isCiBranch try-perf || isCiBranch automation/bors/try; then echo "channel verification is only executed on PR builds" exit fi diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 99ad2847b865e..eac173690b8cc 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 99ad2847b865e96d8ae7b333d3ee96963557e621 +Subproject commit eac173690b8cc99094e1d88bd49dd61127fbd285 diff --git a/src/doc/nomicon b/src/doc/nomicon index e3f3af69dce71..ddfa421448768 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit e3f3af69dce71cd37a785bccb7e58449197d940c +Subproject commit ddfa4214487686e91b21aa29afb972c08a8f0d5b diff --git a/src/doc/reference b/src/doc/reference index ee7c676fd6e28..5262e1c3b43a2 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit ee7c676fd6e287459cb407337652412c990686c0 +Subproject commit 5262e1c3b43a2c489df8f6717683a44c7a2260fd diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 08bb147d51e81..a13b7c28ed705 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 08bb147d51e815b96e8db7ba4cf870f201c11ff8 +Subproject commit a13b7c28ed705891c681ce5417b3d1cdb12cecd1 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 94605e2a21707..5c66338644640 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -28,6 +28,7 @@ - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [\*-android and \*-androideabi](platform-support/android.md) - [\*-linux-ohos](platform-support/openharmony.md) + - [\*-hurd-gnu](platform-support/hurd.md) - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index d72543c7e0255..cfbe1e09cde0c 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -249,11 +249,9 @@ flavor. Valid options are: * `gcc`: use the `cc` executable, which is typically gcc or clang on many systems. * `ld`: use the `ld` executable. * `msvc`: use the `link.exe` executable from Microsoft Visual Studio MSVC. -* `ptx-linker`: use - [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) for Nvidia - NVPTX GPGPU support. -* `bpf-linker`: use - [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support. +* `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) + for Nvidia NVPTX GPGPU support. +* `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support. * `wasm-ld`: use the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html) executable, a port of LLVM `lld` for WebAssembly. * `ld64.lld`: use the LLVM `lld` executable with the [`-flavor darwin` diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 70b35526ee58a..1fb5e56db5d76 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -33,10 +33,10 @@ All tier 1 targets with host tools support the full standard library. target | notes -------|------- `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes] -`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] -`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] -`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) -`x86_64-apple-darwin` | 64-bit macOS (10.7+, Lion+) +`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI] +`x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+) `x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support] `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support] `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) @@ -47,7 +47,10 @@ target | notes [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community. +[^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue]. + [77071]: https://github.com/rust-lang/rust/issues/77071 +[x86-32-float-issue]: https://github.com/rust-lang/rust/issues/114479 ## Tier 1 @@ -90,10 +93,6 @@ target | notes `arm-unknown-linux-gnueabihf` | ARMv6 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) -`mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23) -`mipsel-unknown-linux-gnu` | MIPS (LE) Linux (kernel 4.4, glibc 2.23) `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) @@ -150,17 +149,15 @@ target | std | notes `armv7r-none-eabi` | * | Bare ARMv7-R `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat `asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten -`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE -`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) -`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL -[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android -`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD -`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL +`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87] +`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87] +`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87] +[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI] +`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI] +`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI] [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI -`mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL -`mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL -`mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL -`mipsel-unknown-linux-musl` | ✓ | MIPS (LE) Linux with MUSL +[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) +[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] `riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA) `riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA) @@ -193,6 +190,8 @@ target | std | notes `x86_64-unknown-redox` | ✓ | Redox OS [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI +[^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue]. + [Fortanix ABI]: https://edp.fortanix.com/ ## Tier 3 @@ -245,7 +244,6 @@ target | std | host | notes `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-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 @@ -263,22 +261,29 @@ target | std | host | notes `bpfel-unknown-none` | * | | BPF (little endian) `csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian) `hexagon-unknown-linux-musl` | ? | | -`i386-apple-ios` | ✓ | | 32-bit x86 iOS -[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | -`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) -`i686-pc-windows-msvc` | * | | 32-bit Windows XP support -[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | -`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku -[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 -[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD -`i686-uwp-windows-gnu` | ? | | -`i686-uwp-windows-msvc` | ? | | -`i686-wrs-vxworks` | ? | | -[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) -[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) +`i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI] +[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] +`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI] +`i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI] +[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI] +`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI] +[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI] +[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI] +[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI] +`i686-uwp-windows-gnu` | ? | | [^x86_32-floats-return-ABI] +`i686-uwp-windows-msvc` | ? | | [^x86_32-floats-return-ABI] +`i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI] [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux +`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) +`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl libc `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL +`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23) +`mips64-unknown-linux-muslabi64` | ✓ | | MIPS64 Linux, N64 ABI, musl libc +`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23) +`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl libc +`mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23) +`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl libc `mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) `mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index f8cd92f9257ee..9233a36db3d7e 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -58,7 +58,7 @@ To build a rust toolchain, create a `config.toml` with the following contents: ```toml profile = "compiler" -changelog-seen = 2 +change-id = 115898 [build] sanitizers = true diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md new file mode 100644 index 0000000000000..ddf40213ed49d --- /dev/null +++ b/src/doc/rustc/src/platform-support/hurd.md @@ -0,0 +1,35 @@ +# `i686-unknown-hurd-gnu` + +**Tier: 3** + +[GNU/Hurd] is the GNU Hurd is the GNU project's replacement for the Unix kernel. + +## Target maintainers + +- Samuel Thibault, `samuel.thibault@ens-lyon.org`, https://github.com/sthibaul/ + +## Requirements + +The target supports host tools. + +The GNU/Hurd target supports `std` and uses the standard ELF file format. + +## Building the target + +This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Tests can be run in the same way as a regular binary. + +## Cross-compilation toolchains and C code + +The target supports C code, the GNU toolchain calls the target +`i686-unknown-gnu`. diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index d0ae3425fa8eb..68d7c9d85e444 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -1,6 +1,6 @@ # `loongarch*-unknown-none*` -**Tier: 3** +**Tier: 2** Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc. diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md index 3f1912fc6f951..9203a31e9f4e7 100644 --- a/src/doc/rustc/src/platform-support/mips-release-6.md +++ b/src/doc/rustc/src/platform-support/mips-release-6.md @@ -67,7 +67,7 @@ The following procedure outlines the build process for the MIPS64 R6 target with ### Prerequisite: Disable debuginfo -A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: +An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: ```toml [rust] diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index b376c4a84ac9e..9f0662783a4ec 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -98,7 +98,7 @@ Example content: ```toml profile = "compiler" -changelog-seen = 2 +change-id = 115898 ``` 2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets) diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md index 89539f3888c83..05fd407ed71e9 100644 --- a/src/doc/rustc/src/platform-support/openharmony.md +++ b/src/doc/rustc/src/platform-support/openharmony.md @@ -101,7 +101,7 @@ To build a rust toolchain, create a `config.toml` with the following contents: ```toml profile = "compiler" -changelog-seen = 2 +change-id = 115898 [build] sanitizers = true diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 03fa284620e4c..370939520dc0c 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -19,8 +19,8 @@ Available targets: ## Requirements All UEFI targets can be used as `no-std` environments via cross-compilation. -Support for `std` is missing, but actively worked on. `alloc` is supported if -an allocator is provided by the user. No host tools are supported. +Support for `std` is present, but incomplete and extremely new. `alloc` is supported if +an allocator is provided by the user or if using std. No host tools are supported. The UEFI environment resembles the environment for Microsoft Windows, with some minor differences. Therefore, cross-compiling for UEFI works with the same @@ -230,3 +230,82 @@ pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Statu efi::Status::SUCCESS } ``` + +## Rust std for UEFI +This section contains information on how to use std on UEFI. + +### Build std +The building std part is pretty much the same as the official [docs](https://rustc-dev-guide.rust-lang.org/getting-started.html). +The linker that should be used is `rust-lld`. Here is a sample `config.toml`: +```toml +[rust] +lld = true +``` +Then just build using `x.py`: +```sh +./x.py build --target x86_64-unknown-uefi --stage 1 +``` +Alternatively, it is possible to use the `build-std` feature. However, you must use a toolchain which has the UEFI std patches. +Then just build the project using the following command: +```sh +cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort +``` + +### Implemented features +#### alloc +- Implemented using `EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`. +- Passes all the tests. +- Currently uses `EfiLoaderData` as the `EFI_ALLOCATE_POOL->PoolType`. +#### cmath +- Provided by compiler-builtins. +#### env +- Just some global constants. +#### locks +- The provided locks should work on all standard single-threaded UEFI implementations. +#### os_str +- While the strings in UEFI should be valid UCS-2, in practice, many implementations just do not care and use UTF-16 strings. +- Thus, the current implementation supports full UTF-16 strings. +#### stdio +- Uses `Simple Text Input Protocol` and `Simple Text Output Protocol`. +- Note: UEFI uses CRLF for new line. This means Enter key is registered as CR instead of LF. + +## Example: Hello World With std +The following code features a valid UEFI application, including `stdio` and `alloc` (`OsString` and `Vec`): + +This example can be compiled as binary crate via `cargo` using the toolchain +compiled from the above source (named custom): + +```sh +cargo +custom build --target x86_64-unknown-uefi +``` + +```rust,ignore (platform-specific) +#![feature(uefi_std)] + +use r_efi::{efi, protocols::simple_text_output}; +use std::{ + ffi::OsString, + os::uefi::{env, ffi::OsStrExt} +}; + +pub fn main() { + println!("Starting Rust Application..."); + + // Use System Table Directly + let st = env::system_table().as_ptr() as *mut efi::SystemTable; + let mut s: Vec = OsString::from("Hello World!\n").encode_wide().collect(); + s.push(0); + let r = + unsafe { + let con_out: *mut simple_text_output::Protocol = (*st).con_out; + let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) -> efi::Status = (*con_out).output_string; + output_string(con_out, s.as_ptr() as *mut efi::Char16) + }; + assert!(!r.is_error()) +} +``` + +### BootServices +The current implementation of std makes `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses. + +Note: It should be noted that it is up to the user to drop all allocated memory before `ExitBootServices` is called. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 0d3f6338af45d..7473b09920fba 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -375,7 +375,7 @@ library, as an equivalent command-line argument is provided to `rustc` when buil This feature allows you to generate an index-page with a given markdown file. A good example of it is the [rust documentation index](https://doc.rust-lang.org/nightly/index.html). -With this, you'll have a page which you can custom as much as you want at the top of your crates. +With this, you'll have a page which you can customize as much as you want at the top of your crates. Using `index-page` option enables `enable-index-page` option as well. diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index a6d941f6d0454..b215de6ad28a2 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -367,26 +367,52 @@ where ## Type aliases Keep type aliases on one line when they fit. If necessary to break the line, do -so after the `=`, and block-indent the right-hand side: +so before the `=`, and block-indent the right-hand side: ```rust pub type Foo = Bar; // If multi-line is required -type VeryLongType = - AnEvenLongerType>; +type VeryLongType + = AnEvenLongerType>; ``` -Where possible avoid `where` clauses and keep type constraints inline. Where -that is not possible split the line before and after the `where` clause (and -split the `where` clause as normal), e.g., +When there is a trailing `where` clause after the type, and no `where` clause +present before the type, break before the `=` and indent. Then break before the +`where` keyword and format the clauses normally, e.g., ```rust +// With only a trailing where clause type VeryLongType + = AnEvenLongerType> +where + T: U::AnAssociatedType, + U: SomeBound; +``` + +When there is a `where` clause before the type, format it normally, and break +after the last clause. Do not indent before the `=` to leave it visually +distinct from the indented clauses that precede it. If there is additionally a +`where` clause after the type, break before the `where` keyword and format the +clauses normally. + +```rust +// With only a preceding where clause. +type WithPrecedingWC where T: U::AnAssociatedType, U: SomeBound, = AnEvenLongerType>; + +// Or with both a preceding and trailing where clause. +type WithPrecedingWC +where + T: U::AnAssociatedType, + U: SomeBound, += AnEvenLongerType> +where + T: U::AnAssociatedType2, + U: SomeBound2; ``` ## Associated types diff --git a/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md new file mode 100644 index 0000000000000..a1fcb631c6826 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md @@ -0,0 +1,8 @@ +# `link-native-libraries` + +This option allows ignoring libraries specified in `#[link]` attributes instead of passing them to the linker. +This can be useful in build systems that manage native libraries themselves and pass them manually, +e.g. with `-Clink-arg`. + +- `yes` - Pass native libraries to the linker. Default. +- `no` - Don't pass native libraries to the linker. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 49389b28c8fc7..502853f39ae41 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -197,22 +197,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes): # ControlFlowIntegrity -The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides -forward-edge control flow protection for both Rust-compiled code only and for C -or C++ and Rust -compiled code mixed-language binaries, also known as “mixed -binaries” (i.e., for when C or C++ and Rust -compiled code share the same -virtual address space), by aggregating function pointers in groups identified by -their return and parameter types. - -LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`). -Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the -`-Zsanitizer-cfi-normalize-integers` option to be used with Clang -`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and -proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`). +The LLVM CFI support in the Rust compiler provides forward-edge control flow +protection for both Rust-compiled code only and for C or C++ and Rust -compiled +code mixed-language binaries, also known as “mixed binaries” (i.e., for when C +or C++ and Rust -compiled code share the same virtual address space), by +aggregating function pointers in groups identified by their return and parameter +types. + +LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., +`-Clinker-plugin-lto` or `-Clto`). Cross-language LLVM CFI can be enabled with +`-Zsanitizer=cfi`, and requires the `-Zsanitizer-cfi-normalize-integers` option +to be used with Clang `-fsanitize-cfi-icall-experimental-normalize-integers` +option for cross-language LLVM CFI support, and proper (i.e., non-rustc) LTO +(i.e., `-Clinker-plugin-lto`). + +It is recommended to rebuild the standard library with CFI enabled by using the +Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI. See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. -## Example +## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination ```rust,ignore (making doc tests pass cross-platform is hard) #![feature(naked_functions)] @@ -239,7 +243,7 @@ pub extern "C" fn add_two(x: i32) { nop nop nop - lea eax, [edi+2] + lea eax, [rdi+2] ret ", options(noreturn) @@ -258,8 +262,9 @@ fn main() { println!("With CFI enabled, you should not see the next answer"); let f: fn(i32) -> i32 = unsafe { - // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are - // invalid branch/call destinations (i.e., within the body of the function). + // Offset 0 is a valid branch/call destination (i.e., the function entry + // point), but offsets 1-8 within the landing pad/nop block are invalid + // branch/call destinations (i.e., within the body of the function). mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5)) }; let next_answer = do_twice(f, 5); @@ -267,38 +272,40 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 1. Modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 1. Redirecting control flow using an indirect branch/call to an invalid +destination (i.e., within the body of the function). ```shell $ cargo run --release Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1) - Finished release [optimized] target(s) in 0.76s + Finished release [optimized] target(s) in 0.42s Running `target/release/rust-cfi-1` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 2. Build and execution of the modified example with LLVM CFI disabled. +Fig. 2. Build and execution of Fig. 1 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1) - Finished release [optimized] target(s) in 3.39s - Running `target/release/rust-cfi-1` + Finished release [optimized] target(s) in 1m 08s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-1` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 3. Build and execution of the modified example with LLVM CFI enabled. +Fig. 3. Build and execution of Fig. 1 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to an invalid destination, the execution is terminated (see Fig. 3). +## Example 2: Redirecting control flow using an indirect branch/call to a function with a different number of parameters + ```rust use std::mem; @@ -327,39 +334,42 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 4. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 4. Redirecting control flow using an indirect branch/call to a function +with a different number of parameters than arguments intended/passed in the +call/branch site. ```shell $ cargo run --release Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2) - Finished release [optimized] target(s) in 0.76s + Finished release [optimized] target(s) in 0.43s Running `target/release/rust-cfi-2` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 5. Build and execution of the modified example with LLVM CFI disabled. +Fig. 5. Build and execution of Fig. 4 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2) - Finished release [optimized] target(s) in 3.38s - Running `target/release/rust-cfi-2` + Finished release [optimized] target(s) in 1m 08s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-2` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 6. Build and execution of the modified example with LLVM CFI enabled. +Fig. 6. Build and execution of Fig. 4 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to a function with different number of parameters than arguments intended/passed in the call/branch site, the execution is also terminated (see Fig. 6). +## Example 3: Redirecting control flow using an indirect branch/call to a function with different return and parameter types + ```rust use std::mem; @@ -388,42 +398,46 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 7. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 7. Redirecting control flow using an indirect branch/call to a function +with different return and parameter types than the return type expected and +arguments intended/passed at the call/branch site. ```shell $ cargo run --release Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3) - Finished release [optimized] target(s) in 0.74s + Finished release [optimized] target(s) in 0.44s Running `target/release/rust-cfi-3` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 8. Build and execution of the modified example with LLVM CFI disabled. +Fig. 8. Build and execution of Fig. 7 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3) - Finished release [optimized] target(s) in 3.40s - Running `target/release/rust-cfi-3` + Finished release [optimized] target(s) in 1m 07s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-3` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 9. Build and execution of the modified example with LLVM CFI enabled. +Fig. 9. Build and execution of Fig. 7 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to a function with different return and parameter types than the return type expected and arguments intended/passed in the call/branch site, the execution is also terminated (see Fig. 9). +## Example 4: Redirecting control flow using an indirect branch/call to a function with different return and parameter types across the FFI boundary + ```ignore (cannot-test-this-because-uses-custom-build) int -do_twice(int (*fn)(int), int arg) { +do_twice(int (*fn)(int), int arg) +{ return fn(arg) + fn(arg); } ``` @@ -459,54 +473,49 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 11. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 11. Redirecting control flow using an indirect branch/call to a function +with different return and parameter types than the return type expected and +arguments intended/passed in the call/branch site, across the FFI boundary. ```shell $ make -mkdir -p target/debug -clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc -llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc -RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build - Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1) - Finished dev [unoptimized + debuginfo] target(s) in 0.45s -$ ./target/debug/main +mkdir -p target/release +clang -I. -Isrc -Wall -c src/foo.c -o target/release/libfoo.o +llvm-ar rcs target/release/libfoo.a target/release/libfoo.o +RUSTFLAGS="-L./target/release -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release + Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4) + Finished release [optimized] target(s) in 0.49s +$ ./target/release/rust-cfi-4 The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 12. Build and execution of the modified example with LLVM CFI disabled. +Fig. 12. Build and execution of Figs. 10–11 with LLVM CFI disabled. ```shell $ make -mkdir -p target/debug -clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc -llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc -RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build - Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1) - Finished dev [unoptimized + debuginfo] target(s) in 0.45s -$ ./target/debug/main +mkdir -p target/release +clang -I. -Isrc -Wall -flto -fsanitize=cfi -fsanitize-cfi-icall-experimental-normalize-integers -fvisibility=hidden -c -emit-llvm src/foo.c -o target/release/libfoo.bc +llvm-ar rcs target/release/libfoo.a target/release/libfoo.bc +RUSTFLAGS="-L./target/release -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... + Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4) + Finished release [optimized] target(s) in 1m 06s +$ ./target/x86_64-unknown-linux-gnu/release/rust-cfi-4 The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 13. Build and execution of the modified example with LLVM CFI enabled. - -When LLVM CFI is enabled, if there are any attempts to change/hijack control -flow using an indirect branch/call to a function with different return and -parameter types than the return type expected and arguments intended/passed in -the call/branch site, even across the FFI boundary and for extern "C" function -types indirectly called (i.e., callbacks/function pointers) across the FFI -boundary, in C or C++ and Rust -compiled code mixed-language binaries, also -known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share -the same virtual address space), the execution is also terminated (see Fig. 13). - - -[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html -[rust-book]: https://doc.rust-lang.org/book/title-page.html +Fig. 13. Build and execution of FIgs. 10–11 with LLVM CFI enabled. + +When LLVM CFI is enabled, if there are any attempts to redirect control flow +using an indirect branch/call to a function with different return and parameter +types than the return type expected and arguments intended/passed in the +call/branch site, even across the FFI boundary and for extern "C" function types +indirectly called (i.e., callbacks/function pointers) across the FFI boundary, +the execution is also terminated (see Fig. 13). # HWAddressSanitizer diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 9e20662fff370..32b882e763d65 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -37,7 +37,7 @@ Most lang items are defined by `core`, but if you're trying to build an executable without the `std` crate, you might run into the need for lang item definitions. -[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/personality/gcc.rs ## Example: Implementing a `Box` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 1fade6ce95b89..d9421a428f1ea 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -33,7 +33,7 @@ of a library. Plugins can extend [Rust's lint infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with additional checks for code style, safety, etc. Now let's write a plugin -[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs) +[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs) that warns about any item named `lintme`. ```rust,ignore (requires-stage-2) @@ -43,14 +43,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc_ast::ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); @@ -58,9 +58,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.lint(TEST_LINT, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } } } diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml index 395814e7488bf..85c26ec499343 100644 --- a/src/etc/installer/pkg/Distribution.xml +++ b/src/etc/installer/pkg/Distribution.xml @@ -7,7 +7,7 @@ - + diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a06f31a932919..bdf6a0f6b239e 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -551,8 +551,8 @@ where WherePredicate::RegionPredicate { lifetime, bounds } => { lifetime_to_bounds.entry(lifetime).or_default().extend(bounds); } - WherePredicate::EqPredicate { lhs, rhs, bound_params } => { - match *lhs { + WherePredicate::EqPredicate { lhs, rhs } => { + match lhs { Type::QPath(box QPathData { ref assoc, ref self_type, @@ -590,14 +590,13 @@ where GenericArgs::AngleBracketed { ref mut bindings, .. } => { bindings.push(TypeBinding { assoc: assoc.clone(), - kind: TypeBindingKind::Equality { term: *rhs }, + kind: TypeBindingKind::Equality { term: rhs }, }); } GenericArgs::Parenthesized { .. } => { existing_predicates.push(WherePredicate::EqPredicate { lhs: lhs.clone(), rhs, - bound_params, }); continue; // If something other than a Fn ends up // with parentheses, leave it alone diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index dd43ee0338322..eb18ecf662c14 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,9 +18,9 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item, - clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, - clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, + self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, + clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, + clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; use crate::core::DocContext; @@ -80,7 +80,7 @@ pub(crate) fn try_inline( build_impls(cx, did, attrs_without_docs, &mut ret); clean::UnionItem(build_union(cx, did)) } - Res::Def(DefKind::TyAlias { .. }, did) => { + Res::Def(DefKind::TyAlias, did) => { record_extern_fqn(cx, did, ItemType::TypeAlias); build_impls(cx, did, attrs_without_docs, &mut ret); clean::TypeAliasItem(build_type_alias(cx, did)) @@ -239,20 +239,13 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box { let sig = cx.tcx.fn_sig(did).instantiate_identity(); - - let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { - Some(clean::GenericParamDef::lifetime(name)) - } - _ => None, - }); - let predicates = cx.tcx.explicit_predicates_of(did); + let (generics, decl) = clean::enter_impl_trait(cx, |cx| { // NOTE: generics need to be cleaned before the decl! let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); // FIXME: This does not place parameters in source order (late-bound ones come last) - generics.params.extend(late_bound_regions); + generics.params.extend(clean_bound_vars(sig.bound_vars())); let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig); (generics, decl) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 190b1b038b68a..b9d7acee63c25 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( poly_trait_ref: ty::PolyTraitRef<'tcx>, bindings: ThinVec, ) -> GenericBound { - // collect any late bound regions - let late_bound_regions: Vec<_> = cx - .tcx - .collect_referenced_late_bound_regions(&poly_trait_ref) - .into_iter() - .filter_map(|br| match br { - ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)), - _ => None, - }) - .collect(); - - let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings); GenericBound::TraitBound( - PolyTrait { trait_, generic_params: late_bound_regions }, + PolyTrait { + trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings), + generic_params: clean_bound_vars(poly_trait_ref.bound_vars()), + }, hir::TraitBoundModifier::None, ) } @@ -338,9 +329,8 @@ fn clean_where_predicate<'tcx>( }, hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate { - lhs: Box::new(clean_ty(wrp.lhs_ty, cx)), - rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()), - bound_params: Vec::new(), + lhs: clean_ty(wrp.lhs_ty, cx), + rhs: clean_ty(wrp.rhs_ty, cx).into(), }, }) } @@ -436,20 +426,9 @@ fn clean_projection_predicate<'tcx>( pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, cx: &mut DocContext<'tcx>, ) -> WherePredicate { - let late_bound_regions = cx - .tcx - .collect_referenced_late_bound_regions(&pred) - .into_iter() - .filter_map(|br| match br { - ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)), - _ => None, - }) - .collect(); - WherePredicate::EqPredicate { - lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)), - rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)), - bound_params: late_bound_regions, + lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None), + rhs: clean_middle_term(pred.map_bound(|p| p.term), cx), } } @@ -703,8 +682,8 @@ pub(crate) fn clean_generics<'tcx>( } } } - WherePredicate::EqPredicate { lhs, rhs, bound_params } => { - eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params }); + WherePredicate::EqPredicate { lhs, rhs } => { + eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs }); } } } @@ -793,15 +772,14 @@ fn clean_ty_generics<'tcx>( } Some(clean_generic_param_def(param, cx)) } + ty::GenericParamDefKind::Const { is_host_effect: true, .. } => None, ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)), }) .collect::>(); - // param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)] - let mut impl_trait_proj = FxHashMap::< - u32, - Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec)>, - >::default(); + // param index -> [(trait DefId, associated type name & generics, term)] + let mut impl_trait_proj = + FxHashMap::>)>>::default(); let where_predicates = preds .predicates @@ -853,11 +831,6 @@ fn clean_ty_generics<'tcx>( trait_did, name, proj.map_bound(|p| p.term), - pred.get_bound_params() - .into_iter() - .flatten() - .cloned() - .collect(), )); } @@ -893,9 +866,9 @@ fn clean_ty_generics<'tcx>( let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() }; if let Some(proj) = impl_trait_proj.remove(&idx) { - for (trait_did, name, rhs, bound_params) in proj { + for (trait_did, name, rhs) in proj { let rhs = clean_middle_term(rhs, cx); - simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs); + simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs); } } @@ -1107,10 +1080,7 @@ fn clean_function<'tcx>( clean_args_from_types_and_names(cx, sig.decl.inputs, names) } }; - let mut decl = clean_fn_decl_with_args(cx, sig.decl, args); - if sig.header.is_async() { - decl.output = decl.sugared_async_return_type(); - } + let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args); (generics, decl) }); Box::new(Function { decl, generics }) @@ -1161,12 +1131,16 @@ fn clean_args_from_types_and_body_id<'tcx>( fn clean_fn_decl_with_args<'tcx>( cx: &mut DocContext<'tcx>, decl: &hir::FnDecl<'tcx>, + header: Option<&hir::FnHeader>, args: Arguments, ) -> FnDecl { - let output = match decl.output { + let mut output = match decl.output { hir::FnRetTy::Return(typ) => clean_ty(typ, cx), hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()), }; + if let Some(header) = header && header.is_async() { + output = output.sugared_async_return_type(); + } FnDecl { inputs: args, output, c_variadic: decl.c_variadic } } @@ -1179,7 +1153,17 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( // We assume all empty tuples are default return type. This theoretically can discard `-> ()`, // but shouldn't change any code meaning. - let output = clean_middle_ty(sig.output(), cx, None, None); + let mut output = clean_middle_ty(sig.output(), cx, None, None); + + // If the return type isn't an `impl Trait`, we can safely assume that this + // function isn't async without needing to execute the query `asyncness` at + // all which gives us a noticeable performance boost. + if let Some(did) = did + && let Type::ImplTrait(_) = output + && cx.tcx.asyncness(did).is_async() + { + output = output.sugared_async_return_type(); + } FnDecl { output, @@ -1351,23 +1335,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } ty::AssocKind::Fn => { let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity(); - - let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(_, name)) - if name != kw::UnderscoreLifetime => - { - Some(GenericParamDef::lifetime(name)) - } - _ => None, - }); - let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), tcx.explicit_predicates_of(assoc_item.def_id), ); // FIXME: This does not place parameters in source order (late-bound ones come last) - generics.params.extend(late_bound_regions); + generics.params.extend(clean_bound_vars(sig.bound_vars())); let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig); @@ -1752,7 +1726,7 @@ fn maybe_expand_private_type_alias<'tcx>( cx: &mut DocContext<'tcx>, path: &hir::Path<'tcx>, ) -> Option { - let Res::Def(DefKind::TyAlias { .. }, def_id) = path.res else { return None }; + let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None }; // Substitute private type aliases let def_id = def_id.as_local()?; let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id()) @@ -2021,7 +1995,7 @@ impl<'tcx> ContainerTy<'tcx> { let (DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Trait) = tcx.def_kind(container) else { return ObjectLifetimeDefault::Empty; @@ -2103,9 +2077,11 @@ pub(crate) fn clean_middle_ty<'tcx>( // FIXME: should we merge the outer and inner binders somehow? let sig = bound_ty.skip_binder().fn_sig(cx.tcx); let decl = clean_fn_decl_from_did_and_sig(cx, None, sig); + let generic_params = clean_bound_vars(sig.bound_vars()); + BareFunction(Box::new(BareFunctionDecl { unsafety: sig.unsafety(), - generic_params: Vec::new(), + generic_params, decl, abi: sig.abi(), })) @@ -2181,8 +2157,8 @@ pub(crate) fn clean_middle_ty<'tcx>( let late_bound_regions: FxIndexSet<_> = obj .iter() - .flat_map(|pb| pb.bound_vars()) - .filter_map(|br| match br { + .flat_map(|pred| pred.bound_vars()) + .filter_map(|var| match var { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { @@ -2256,6 +2232,11 @@ pub(crate) fn clean_middle_ty<'tcx>( } } + ty::Bound(_, ref ty) => match ty.kind { + ty::BoundTyKind::Param(_, name) => Generic(name), + ty::BoundTyKind::Anon => panic!("unexpected anonymous bound type variable"), + }, + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // If it's already in the same alias, don't get an infinite loop. if cx.current_type_aliases.contains_key(&def_id) { @@ -2284,10 +2265,8 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Closure(..) => panic!("Closure"), ty::Generator(..) => panic!("Generator"), - ty::Bound(..) => panic!("Bound"), ty::Placeholder(..) => panic!("Placeholder"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), - ty::GeneratorWitnessMIR(..) => panic!("GeneratorWitnessMIR"), ty::Infer(..) => panic!("Infer"), ty::Error(_) => rustc_errors::FatalError.raise(), } @@ -2566,7 +2545,7 @@ fn clean_bare_fn_ty<'tcx>( .map(|x| clean_generic_param(cx, None, x)) .collect(); let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names); - let decl = clean_fn_decl_with_args(cx, bare_fn.decl, args); + let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args); (generic_params, decl) }); BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params } @@ -2854,7 +2833,7 @@ fn clean_impl<'tcx>( let for_ = clean_ty(impl_.self_ty, cx); let type_alias = for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) { - DefKind::TyAlias { .. } => Some(clean_middle_ty( + DefKind::TyAlias => Some(clean_middle_ty( ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id.to_def_id()), @@ -3077,7 +3056,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); let args = clean_args_from_types_and_names(cx, decl.inputs, names); - let decl = clean_fn_decl_with_args(cx, decl, args); + let decl = clean_fn_decl_with_args(cx, decl, None, args); (generics, decl) }); ForeignFunctionItem(Box::new(Function { decl, generics })) @@ -3116,3 +3095,30 @@ fn clean_type_binding<'tcx>( }, } } + +fn clean_bound_vars<'tcx>( + bound_vars: &'tcx ty::List, +) -> Vec { + bound_vars + .into_iter() + .filter_map(|var| match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + if name != kw::UnderscoreLifetime => + { + Some(GenericParamDef::lifetime(name)) + } + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(did, name)) => Some(GenericParamDef { + name, + kind: GenericParamDefKind::Type { + did, + bounds: Vec::new(), + default: None, + synthetic: false, + }, + }), + // FIXME(non_lifetime_binders): Support higher-ranked const parameters. + ty::BoundVariableKind::Const => None, + _ => None, + }) + .collect() +} diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 7b8f20326ed47..eea8c1906c5b5 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec { lifetimes.push((lifetime, bounds)); } - WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)), + WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)), } } // Look for equality predicates on associated types that can be merged into // general bound predicates. - equalities.retain(|(lhs, rhs, bound_params)| { + equalities.retain(|(lhs, rhs)| { let Some((ty, trait_did, name)) = lhs.projection() else { return true; }; let Some((bounds, _)) = tybounds.get_mut(ty) else { return true }; - merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs) + merge_bounds(cx, bounds, trait_did, name, rhs) }); // And finally, let's reassemble everything @@ -64,18 +64,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec, bounds: &mut Vec, - mut bound_params: Vec, trait_did: DefId, assoc: clean::PathSegment, rhs: &clean::Term, @@ -93,12 +88,6 @@ pub(crate) fn merge_bounds( } let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); - trait_ref.generic_params.append(&mut bound_params); - // Sort parameters (likely) originating from a hashset alphabetically to - // produce predictable output (and to allow for full deduplication). - trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str())); - trait_ref.generic_params.dedup_by_key(|p| p.name); - match last.args { PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ef7794cc41e2c..48ce0a8944996 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -31,7 +31,7 @@ use rustc_resolve::rustdoc::{ use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{self, FileName, Loc}; +use rustc_span::{self, FileName, Loc, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; @@ -622,7 +622,7 @@ impl Item { fn build_fn_header( def_id: DefId, tcx: TyCtxt<'_>, - asyncness: hir::IsAsync, + asyncness: ty::Asyncness, ) -> hir::FnHeader { let sig = tcx.fn_sig(def_id).skip_binder(); let constness = @@ -631,6 +631,10 @@ impl Item { } else { hir::Constness::NotConst }; + let asyncness = match asyncness { + ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP), + ty::Asyncness::No => hir::IsAsync::NotAsync, + }; hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness } } let header = match *self.kind { @@ -1285,7 +1289,7 @@ impl Lifetime { pub(crate) enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: Box, rhs: Box, bound_params: Vec }, + EqPredicate { lhs: Type, rhs: Term }, } impl WherePredicate { @@ -1296,15 +1300,6 @@ impl WherePredicate { _ => None, } } - - pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> { - match self { - Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => { - Some(bound_params) - } - _ => None, - } - } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -1380,28 +1375,6 @@ impl FnDecl { pub(crate) fn self_type(&self) -> Option { self.inputs.values.get(0).and_then(|v| v.to_self()) } - - /// Returns the sugared return type for an async function. - /// - /// For example, if the return type is `impl std::future::Future`, this function - /// will return `i32`. - /// - /// # Panics - /// - /// This function will panic if the return type does not match the expected sugaring for async - /// functions. - pub(crate) fn sugared_async_return_type(&self) -> Type { - if let Type::ImplTrait(v) = &self.output && - let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..] - { - let bindings = trait_.bindings().unwrap(); - let ret_ty = bindings[0].term(); - let ty = ret_ty.ty().expect("Unexpected constant return term"); - ty.clone() - } else { - panic!("unexpected desugaring of async function") - } - } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -1613,6 +1586,30 @@ impl Type { } } + /// Returns the sugared return type for an async function. + /// + /// For example, if the return type is `impl std::future::Future`, this function + /// will return `i32`. + /// + /// # Panics + /// + /// This function will panic if the return type does not match the expected sugaring for async + /// functions. + pub(crate) fn sugared_async_return_type(self) -> Type { + if let Type::ImplTrait(mut v) = self + && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _ )) = v.pop() + && let Some(segment) = trait_.segments.pop() + && let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args + && let Some(binding) = bindings.pop() + && let TypeBindingKind::Equality { term } = binding.kind + && let Term::Type(ty) = term + { + ty + } else { + panic!("unexpected async fn return type") + } + } + /// Checks if this is a `T::Name` path for an associated type. pub(crate) fn is_assoc_ty(&self) -> bool { match self { @@ -2087,9 +2084,8 @@ impl Discriminant { pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option { self.expr.map(|body| rendered_const(tcx, body)) } - /// Will always be a machine readable number, without underscores or suffixes. - pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String { - print_evaluated_const(tcx, self.value, false).unwrap() + pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String { + print_evaluated_const(tcx, self.value, with_underscores, false).unwrap() } } @@ -2185,16 +2181,6 @@ impl Path { } }) } - - pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> { - self.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { - Some(&**bindings) - } else { - None - } - }) - } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -2344,7 +2330,7 @@ impl ConstantKind { match *self { ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None, ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { - print_evaluated_const(tcx, def_id, true) + print_evaluated_const(tcx, def_id, true, true) } } } @@ -2474,15 +2460,6 @@ pub(crate) enum TypeBindingKind { Constraint { bounds: Vec }, } -impl TypeBinding { - pub(crate) fn term(&self) -> &Term { - match self.kind { - TypeBindingKind::Equality { ref term } => term, - _ => panic!("expected equality type binding for parenthesized generic args"), - } - } -} - /// The type, lifetime, or constant that a private type alias's parameter should be /// replaced with when expanding a use of that type alias. /// diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e680b451421c1..01078504b713a 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -275,7 +275,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { pub(crate) fn print_evaluated_const( tcx: TyCtxt<'_>, def_id: DefId, - underscores_and_type: bool, + with_underscores: bool, + with_type: bool, ) -> Option { tcx.const_eval_poly(def_id).ok().and_then(|val| { let ty = tcx.type_of(def_id).instantiate_identity(); @@ -283,8 +284,8 @@ pub(crate) fn print_evaluated_const( (_, &ty::Ref(..)) => None, (mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None, (mir::ConstValue::Scalar(_), _) => { - let const_ = mir::ConstantKind::from_value(val, ty); - Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type)) + let const_ = mir::Const::from_value(val, ty); + Some(print_const_with_custom_print_scalar(tcx, const_, with_underscores, with_type)) } _ => None, } @@ -319,33 +320,38 @@ fn format_integer_with_underscore_sep(num: &str) -> String { fn print_const_with_custom_print_scalar<'tcx>( tcx: TyCtxt<'tcx>, - ct: mir::ConstantKind<'tcx>, - underscores_and_type: bool, + ct: mir::Const<'tcx>, + with_underscores: bool, + with_type: bool, ) -> String { // Use a slightly different format for integer types which always shows the actual value. // For all other types, fallback to the original `pretty_print_const`. match (ct, ct.ty().kind()) { - (mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => { - if underscores_and_type { - format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str()) + (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => { + let mut output = if with_underscores { + format_integer_with_underscore_sep(&int.to_string()) } else { int.to_string() + }; + if with_type { + output += ui.name_str(); } + output } - (mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => { + (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => { let ty = ct.ty(); let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; let data = int.assert_bits(size); let sign_extended_data = size.sign_extend(data) as i128; - if underscores_and_type { - format!( - "{}{}", - format_integer_with_underscore_sep(&sign_extended_data.to_string()), - i.name_str() - ) + let mut output = if with_underscores { + format_integer_with_underscore_sep(&sign_extended_data.to_string()) } else { sign_extended_data.to_string() + }; + if with_type { + output += i.name_str(); } + output } _ => ct.to_string(), } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 7cd25ef444b12..3e6066c78fba2 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -263,7 +263,7 @@ pub(crate) fn create_config( lint_caps, parse_sess_created: None, register_lints: Some(Box::new(crate::lint::register_lints)), - override_queries: Some(|_sess, providers, _external_providers| { + override_queries: Some(|_sess, providers| { // We do not register late module lints, so this only runs `MissingDoc`. // Most lints will require typechecking, so just don't run them. providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 24597c3aca312..741d329fb1922 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -681,7 +681,7 @@ pub(crate) fn make_test( if s.contains(crate_name) { // rustdoc implicitly inserts an `extern crate` item for the own crate // which may be unused, so we need to allow the lint. - prog.push_str(&format!("#[allow(unused_extern_crates)]\n")); + prog.push_str("#[allow(unused_extern_crates)]\n"); prog.push_str(&format!("extern crate r#{crate_name};\n")); line_offset += 1; diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index fd79160ff4a81..be2ee7915889a 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -115,7 +115,7 @@ impl From for ItemType { DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, - DefKind::TyAlias { .. } => Self::TypeAlias, + DefKind::TyAlias => Self::TypeAlias, DefKind::TraitAlias => Self::TraitAlias, DefKind::Macro(kind) => match kind { MacroKind::Bang => ItemType::Macro, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2f611c31a0746..1983bb11e5b11 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -326,8 +326,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( bounds_display.truncate(bounds_display.len() - " + ".len()); write!(f, "{}: {bounds_display}", lifetime.print()) } - // FIXME(fmease): Render bound params. - clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => { + clean::WherePredicate::EqPredicate { lhs, rhs } => { if f.alternate() { write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx)) } else { @@ -1599,7 +1598,7 @@ impl PrintWithSpace for hir::Unsafety { impl PrintWithSpace for hir::IsAsync { fn print_with_space(&self) -> &str { match self { - hir::IsAsync::Async => "async ", + hir::IsAsync::Async(_) => "async ", hir::IsAsync::NotAsync => "", } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 6dbf2185e3d03..d24e6e5faf521 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1083,7 +1083,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } fn parse_in_attribute_block(&mut self) -> Option> { - while let Some((pos, c)) = self.inner.next() { + if let Some((pos, c)) = self.inner.next() { if c == '}' { self.is_in_attribute_block = false; return self.next(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c6751c9585ee9..467493cb0b30d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -5,10 +5,12 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; +use rustc_index::IndexVec; use rustc_middle::middle::stability; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_target::abi::VariantIdx; use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::fmt; @@ -1257,13 +1259,14 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c w, cx, Some(&t.generics), - variants_iter(), + &variants, variants_count, has_stripped_entries, *is_non_exhaustive, + it.def_id().unwrap(), ) }); - item_variants(w, cx, it, variants_iter()); + item_variants(w, cx, it, &variants); } clean::TypeAliasInnerType::Union { fields } => { wrap_item(w, |w| { @@ -1416,36 +1419,81 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: it.name.unwrap(), e.generics.print(cx), ); + render_enum_fields( w, cx, Some(&e.generics), - e.variants(), + &e.variants, count_variants, e.has_stripped_entries(), it.is_non_exhaustive(), + it.def_id().unwrap(), ); }); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if count_variants != 0 { - item_variants(w, cx, it, e.variants()); + item_variants(w, cx, it, &e.variants); } let def_id = it.item_id.expect_def_id(); write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } -fn render_enum_fields<'a>( +/// It'll return true if all variants are C-like variants and if at least one of them has a value +/// set. +fn should_show_enum_discriminant(variants: &IndexVec) -> bool { + let mut has_variants_with_value = false; + for variant in variants { + if let clean::VariantItem(ref var) = *variant.kind && + matches!(var.kind, clean::VariantKind::CLike) + { + has_variants_with_value |= var.discriminant.is_some(); + } else { + return false; + } + } + has_variants_with_value +} + +fn display_c_like_variant( + w: &mut Buffer, + cx: &mut Context<'_>, + item: &clean::Item, + variant: &clean::Variant, + index: VariantIdx, + should_show_enum_discriminant: bool, + enum_def_id: DefId, +) { + let name = item.name.unwrap(); + if let Some(ref value) = variant.discriminant { + write!(w, "{} = {}", name.as_str(), value.value(cx.tcx(), true)); + } else if should_show_enum_discriminant { + let adt_def = cx.tcx().adt_def(enum_def_id); + let discr = adt_def.discriminant_for_variant(cx.tcx(), index); + if discr.ty.is_signed() { + write!(w, "{} = {}", name.as_str(), discr.val as i128); + } else { + write!(w, "{} = {}", name.as_str(), discr.val); + } + } else { + w.write_str(name.as_str()); + } +} + +fn render_enum_fields( mut w: &mut Buffer, cx: &mut Context<'_>, g: Option<&clean::Generics>, - variants: impl Iterator, + variants: &IndexVec, count_variants: usize, has_stripped_entries: bool, is_non_exhaustive: bool, + enum_def_id: DefId, ) { + let should_show_enum_discriminant = should_show_enum_discriminant(variants); if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) { // If there wasn't a `where` clause, we add a whitespace. w.write_str(" "); @@ -1461,15 +1509,24 @@ fn render_enum_fields<'a>( toggle_open(&mut w, format_args!("{count_variants} variants")); } const TAB: &str = " "; - for v in variants { + for (index, v) in variants.iter_enumerated() { + if v.is_stripped() { + continue; + } w.write_str(TAB); - let name = v.name.unwrap(); match *v.kind { - // FIXME(#101337): Show discriminant clean::VariantItem(ref var) => match var.kind { - clean::VariantKind::CLike => w.write_str(name.as_str()), + clean::VariantKind::CLike => display_c_like_variant( + w, + cx, + v, + var, + index, + should_show_enum_discriminant, + enum_def_id, + ), clean::VariantKind::Tuple(ref s) => { - write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); + write!(w, "{}({})", v.name.unwrap(), print_tuple_struct_fields(cx, s)); } clean::VariantKind::Struct(ref s) => { render_struct(w, v, None, None, &s.fields, TAB, false, cx); @@ -1490,11 +1547,11 @@ fn render_enum_fields<'a>( } } -fn item_variants<'a>( +fn item_variants( w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, - variants: impl Iterator, + variants: &IndexVec, ) { let tcx = cx.tcx(); write!( @@ -1507,7 +1564,11 @@ fn item_variants<'a>( document_non_exhaustive_header(it), document_non_exhaustive(it) ); - for variant in variants { + let should_show_enum_discriminant = should_show_enum_discriminant(variants); + for (index, variant) in variants.iter_enumerated() { + if variant.is_stripped() { + continue; + } let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( w, @@ -1522,7 +1583,22 @@ fn item_variants<'a>( it.const_stable_since(tcx), " rightside", ); - write!(w, "

{name}", name = variant.name.unwrap()); + w.write_str("

"); + if let clean::VariantItem(ref var) = *variant.kind && + let clean::VariantKind::CLike = var.kind + { + display_c_like_variant( + w, + cx, + variant, + var, + index, + should_show_enum_discriminant, + it.def_id().unwrap(), + ); + } else { + w.write_str(variant.name.unwrap().as_str()); + } let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 2f0cae0a48e21..7a282a99e9ce9 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1555,7 +1555,7 @@ function initSearch(rawSearchIndex) { return false; } } - } else if (fnType.id !== null) { + } else { if (queryElem.id === typeNameIdOfArrayOrSlice && (fnType.id === typeNameIdOfSlice || fnType.id === typeNameIdOfArray) ) { diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 287cbab07d2b2..b8b7785a2a191 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -9,12 +9,12 @@

{# #} Note: Most layout information is completely {#+ #} unstable and may even differ between compilations. {#+ #} The only exception is types with certain repr(...) {#+ #} - attributes. Please see the Rust Reference’s {#+ #} + attributes. Please see the Rust Reference's {#+ #} “Type Layout” {#+ #} chapter for details on type layout guarantees. {# #}

{# #} {# #} -

Size: {{ type_layout_size|safe }}

{# #} +

Size: {{+ type_layout_size|safe }}

{# #} {% if !variants.is_empty() %}

{# #} Size for each variant: {# #} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 0886501596056..e7f782bb6a65e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -506,9 +506,8 @@ impl FromWithTcx for WherePredicate { lifetime: convert_lifetime(lifetime), bounds: bounds.into_tcx(tcx), }, - // FIXME(fmease): Convert bound parameters as well. - EqPredicate { lhs, rhs, bound_params: _ } => { - WherePredicate::EqPredicate { lhs: (*lhs).into_tcx(tcx), rhs: (*rhs).into_tcx(tcx) } + EqPredicate { lhs, rhs } => { + WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) } } } } @@ -745,7 +744,7 @@ impl FromWithTcx for Discriminant { // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines // the expr is always some. expr: disr.expr(tcx).unwrap(), - value: disr.value(tcx), + value: disr.value(tcx, false), } } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 2f88f6dc6e0aa..fc2acb6eaa358 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -503,13 +503,6 @@ fn opts() -> Vec { "PATH", ) }), - unstable("disable-per-crate-search", |o| { - o.optflagmulti( - "", - "disable-per-crate-search", - "disables generating the crate selector on the search box", - ) - }), unstable("persist-doctests", |o| { o.optopt( "", diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0db846bfc7e34..d216305e6a97d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -522,8 +522,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Alias(..) | ty::Closure(..) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Dynamic(..) | ty::Param(_) | ty::Bound(..) @@ -594,7 +593,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .unwrap_or(Vec::new()) } } - Res::Def(DefKind::TyAlias { .. }, did) => { + Res::Def(DefKind::TyAlias, did) => { // Resolve the link on the type the alias points to. // FIXME: if the associated item is defined directly on the type alias, // it will show up on its documentation page, we should link there instead. diff --git a/src/llvm-project b/src/llvm-project index 42263494d29fe..d404cba4e39df 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 42263494d29febc26d3c1ebdaa7b63677573ec47 +Subproject commit d404cba4e39df595710869988ded7cbe1104b52f diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 778609da062cd..5153dd26f4ad4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -69,7 +69,6 @@ static TARGETS: &[&str] = &[ "arm-unknown-linux-musleabihf", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", - "armv7-apple-ios", "armv7-linux-androideabi", "thumbv7neon-linux-androideabi", "armv7-unknown-linux-gnueabi", @@ -99,6 +98,8 @@ static TARGETS: &[&str] = &[ "i686-unknown-linux-musl", "i686-unknown-uefi", "loongarch64-unknown-linux-gnu", + "loongarch64-unknown-none", + "loongarch64-unknown-none-softfloat", "m68k-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2", "mips-unknown-linux-gnu", diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index a8505ec95967d..09489b0d9b7da 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -82,15 +82,15 @@ pub mod gha { fn start_group(name: impl std::fmt::Display) { if is_in_gha() { - eprintln!("::group::{name}"); + println!("::group::{name}"); } else { - eprintln!("{name}") + println!("{name}") } } fn end_group() { if is_in_gha() { - eprintln!("::endgroup::"); + println!("::endgroup::"); } } diff --git a/src/tools/cargo b/src/tools/cargo index b4ddf95ad9954..794d0a82547f3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b4ddf95ad9954118ac0dae835f2966394ad04c02 +Subproject commit 794d0a82547f3081044c0aca7b6083733ce51344 diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index 7d25b6a2b79e7..30bd476332f75 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: '14.x' + node-version: '18.x' - name: Install remark run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm @@ -29,19 +29,19 @@ jobs: - name: Install mdbook run: | mkdir mdbook - curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.28/mdbook-v0.4.28-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook + curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.34/mdbook-v0.4.34-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook echo `pwd`/mdbook >> $GITHUB_PATH # Run - name: Check *.md files - run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null + run: ./node_modules/.bin/remark -u lint -f . - name: Linkcheck book run: | rustup toolchain install nightly --component rust-docs curl https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh -o linkcheck.sh sh linkcheck.sh clippy --path ./book - + - name: Build mdbook run: mdbook build book diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index a7ae4a0ee2c09..fef25ad8635ae 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,101 @@ document. ## Unreleased / Beta / In Rust Nightly -[37f4c172...master](https://github.com/rust-lang/rust-clippy/compare/37f4c172...master) +[1e8fdf49...master](https://github.com/rust-lang/rust-clippy/compare/1e8fdf49...master) + +## Rust 1.73 + +Current stable, released 2023-10-05 + +[View all 103 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-07-02T12%3A24%3A40Z..2023-08-11T11%3A09%3A56Z+base%3Amaster) + +### New Lints + +* [`impossible_comparisons`] + [#10843](https://github.com/rust-lang/rust-clippy/pull/10843) +* [`redundant_comparisons`] + [#10843](https://github.com/rust-lang/rust-clippy/pull/10843) +* [`ignored_unit_patterns`] + [#11242](https://github.com/rust-lang/rust-clippy/pull/11242) +* [`readonly_write_lock`] + [#11210](https://github.com/rust-lang/rust-clippy/pull/11210) +* [`filter_map_bool_then`] + [#11115](https://github.com/rust-lang/rust-clippy/pull/11115) +* [`needless_return_with_question_mark`] + [#11031](https://github.com/rust-lang/rust-clippy/pull/11031) +* [`redundant_guards`] + [#10955](https://github.com/rust-lang/rust-clippy/pull/10955) +* [`redundant_locals`] + [#10885](https://github.com/rust-lang/rust-clippy/pull/10885) +* [`absolute_paths`] + [#11003](https://github.com/rust-lang/rust-clippy/pull/11003) +* [`error_impl_error`] + [#11107](https://github.com/rust-lang/rust-clippy/pull/11107) +* [`iter_skip_zero`] + [#11046](https://github.com/rust-lang/rust-clippy/pull/11046) +* [`string_lit_chars_any`] + [#11052](https://github.com/rust-lang/rust-clippy/pull/11052) +* [`four_forward_slashes`] + [#11140](https://github.com/rust-lang/rust-clippy/pull/11140) +* [`format_collect`] + [#11116](https://github.com/rust-lang/rust-clippy/pull/11116) +* [`needless_pass_by_ref_mut`] + [#10900](https://github.com/rust-lang/rust-clippy/pull/10900) +* [`manual_is_infinite`] + [#11049](https://github.com/rust-lang/rust-clippy/pull/11049) +* [`manual_is_finite`] + [#11049](https://github.com/rust-lang/rust-clippy/pull/11049) +* [`incorrect_partial_ord_impl_on_ord_type`] + [#10788](https://github.com/rust-lang/rust-clippy/pull/10788) +* [`read_line_without_trim`] + [#10970](https://github.com/rust-lang/rust-clippy/pull/10970) +* [`type_id_on_box`] + [#10987](https://github.com/rust-lang/rust-clippy/pull/10987) + +### Moves and Deprecations + +* Renamed `unwrap_or_else_default` to [`unwrap_or_default`] + [#10120](https://github.com/rust-lang/rust-clippy/pull/10120) +* Moved [`tuple_array_conversions`] to `pedantic` (Now allow-by-default) + [#11146](https://github.com/rust-lang/rust-clippy/pull/11146) +* Moved [`arc_with_non_send_sync`] to `suspicious` (Now warn-by-default) + [#11104](https://github.com/rust-lang/rust-clippy/pull/11104) +* Moved [`needless_raw_string_hashes`] to `pedantic` (Now allow-by-default) + [#11415](https://github.com/rust-lang/rust-clippy/pull/11415) + +### Enhancements + +* [`unwrap_used`]: No longer lints on the never-type or never-like enums + [#11252](https://github.com/rust-lang/rust-clippy/pull/11252) +* [`expect_used`]: No longer lints on the never-type or never-like enums + [#11252](https://github.com/rust-lang/rust-clippy/pull/11252) + +### False Positive Fixes + +* [`panic_in_result_fn`]: No longer triggers on `todo!`, `unimplemented!`, `unreachable!` + [#11123](https://github.com/rust-lang/rust-clippy/pull/11123) + +### Suggestion Fixes/Improvements + +* [`semicolon_if_nothing_returned`]: The suggestion is now machine-applicable with rustfix + [#11083](https://github.com/rust-lang/rust-clippy/pull/11083) + +### ICE Fixes + +* [`filter_map_bool_then`]: No longer crashes on late-bound regions + [#11318](https://github.com/rust-lang/rust-clippy/pull/11318) +* [`unwrap_or_default`]: No longer crashes on alias types for local items + [#11258](https://github.com/rust-lang/rust-clippy/pull/11258) +* [`unnecessary_literal_unwrap`]: No longer crashes on `None.unwrap_or_default()` + [#11106](https://github.com/rust-lang/rust-clippy/pull/11106) +* Fixed MIR-related ICE + [#11130](https://github.com/rust-lang/rust-clippy/pull/11130) +* [`missing_fields_in_debug`]: No longer crashes on non-ADT self types + [#11069](https://github.com/rust-lang/rust-clippy/pull/11069) ## Rust 1.72 -Current stable, released 2023-08-24 +Released 2023-08-24 [View all 131 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-05-22T14%3A53%3A59Z..2023-07-01T22%3A57%3A20Z+base%3Amaster) @@ -5011,6 +5101,7 @@ Released 2018-09-13 [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref +[`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering [`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref @@ -5036,6 +5127,7 @@ Released 2018-09-13 [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next [`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero [`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_with_drain +[`iter_without_into_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_without_into_iter [`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero [`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits [`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays @@ -5072,6 +5164,7 @@ Released 2018-09-13 [`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten +[`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one [`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite @@ -5171,6 +5264,7 @@ Released 2018-09-13 [`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool_assign [`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow [`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference +[`needless_borrows_for_generic_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main @@ -5245,6 +5339,7 @@ Released 2018-09-13 [`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl [`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite +[`path_ends_with_ext`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch [`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters @@ -5279,6 +5374,7 @@ Released 2018-09-13 [`readonly_write_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#readonly_write_lock [`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation +[`redundant_as_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_as_str [`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block [`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_at_rest_pattern [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone @@ -5437,6 +5533,7 @@ Released 2018-09-13 [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap +[`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings @@ -5574,5 +5671,6 @@ Released 2018-09-13 [`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings [`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates +[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 2d8b590dbe311..cbcb42dad79b2 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.74" +version = "0.1.75" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -25,6 +25,8 @@ clippy_lints = { path = "clippy_lints" } rustc_tools_util = "0.3.0" tempfile = { version = "3.2", optional = true } termize = "0.1" +color-print = "0.3.4" # Sync version with Cargo +anstream = "0.5.0" [dev-dependencies] ui_test = "0.20" @@ -38,7 +40,6 @@ itertools = "0.10.1" # UI test dependencies clippy_utils = { path = "clippy_utils" } -derive-new = "0.5" if_chain = "1.0" quote = "1.0" serde = { version = "1.0.125", features = ["derive"] } diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index f6f0c95c72933..e001197842bdc 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -261,7 +261,7 @@ impl EarlyLintPass for FooFunctions {} [declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 [example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 +[category_level_mapping]: ../index.html ## Lint registration diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 52c795e04fe95..2c958ccbbc246 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -151,6 +151,7 @@ The minimum rust version that the project supports * [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) * [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) +* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) ## `cognitive-complexity-threshold` @@ -703,7 +704,7 @@ Minimum chars an ident can have, anything below or equal to this will be linted. ## `accept-comment-above-statement` Whether to accept a safety comment to be placed above the statement containing the `unsafe` block -**Default Value:** `false` (`bool`) +**Default Value:** `true` (`bool`) --- **Affected lints:** @@ -713,7 +714,7 @@ Whether to accept a safety comment to be placed above the statement containing t ## `accept-comment-above-attributes` Whether to accept a safety comment to be placed above the attributes for the `unsafe` block -**Default Value:** `false` (`bool`) +**Default Value:** `true` (`bool`) --- **Affected lints:** @@ -751,6 +752,16 @@ Which crates to allow absolute paths from * [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) +## `allowed-dotfiles` +Additional dotfiles (files or directories starting with a dot) to allow + +**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet`) + +--- +**Affected lints:** +* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) + + ## `enforce-iter-loop-reborrow` #### Example ``` diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index e64cf2c874968..be2386bb1d24b 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -58,7 +58,7 @@ pub fn create( }; create_lint(&lint, msrv).context("Unable to create lint implementation")?; - create_test(&lint).context("Unable to create a test for the new lint")?; + create_test(&lint, msrv).context("Unable to create a test for the new lint")?; if lint.ty.is_none() { add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?; @@ -88,15 +88,21 @@ fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { } } -fn create_test(lint: &LintData<'_>) -> io::Result<()> { - fn create_project_layout>(lint_name: &str, location: P, case: &str, hint: &str) -> io::Result<()> { +fn create_test(lint: &LintData<'_>, msrv: bool) -> io::Result<()> { + fn create_project_layout>( + lint_name: &str, + location: P, + case: &str, + hint: &str, + msrv: bool, + ) -> io::Result<()> { let mut path = location.into().join(case); fs::create_dir(&path)?; write_file(path.join("Cargo.toml"), get_manifest_contents(lint_name, hint))?; path.push("src"); fs::create_dir(&path)?; - write_file(path.join("main.rs"), get_test_file_contents(lint_name))?; + write_file(path.join("main.rs"), get_test_file_contents(lint_name, msrv))?; Ok(()) } @@ -106,13 +112,25 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> { let test_dir = lint.project_root.join(&relative_test_dir); fs::create_dir(&test_dir)?; - create_project_layout(lint.name, &test_dir, "fail", "Content that triggers the lint goes here")?; - create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint")?; + create_project_layout( + lint.name, + &test_dir, + "fail", + "Content that triggers the lint goes here", + msrv, + )?; + create_project_layout( + lint.name, + &test_dir, + "pass", + "This file should not trigger the lint", + false, + )?; println!("Generated test directories: `{relative_test_dir}/pass`, `{relative_test_dir}/fail`"); } else { let test_path = format!("tests/ui/{}.rs", lint.name); - let test_contents = get_test_file_contents(lint.name); + let test_contents = get_test_file_contents(lint.name, msrv); write_file(lint.project_root.join(&test_path), test_contents)?; println!("Generated test file: `{test_path}`"); @@ -194,8 +212,8 @@ pub(crate) fn get_stabilization_version() -> String { parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") } -fn get_test_file_contents(lint_name: &str) -> String { - formatdoc!( +fn get_test_file_contents(lint_name: &str, msrv: bool) -> String { + let mut test = formatdoc!( r#" #![warn(clippy::{lint_name})] @@ -203,7 +221,29 @@ fn get_test_file_contents(lint_name: &str) -> String { // test code goes here }} "# - ) + ); + + if msrv { + let _ = writedoc!( + test, + r#" + + // TODO: set xx to the version one below the MSRV used by the lint, and yy to + // the version used by the lint + #[clippy::msrv = "1.xx"] + fn msrv_1_xx() {{ + // a simple example that would trigger the lint if the MSRV were met + }} + + #[clippy::msrv = "1.yy"] + fn msrv_1_yy() {{ + // the same example as above + }} + "# + ); + } + + test } fn get_manifest_contents(lint_name: &str, hint: &str) -> String { @@ -258,7 +298,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { ) }); - let _: fmt::Result = write!(result, "{}", get_lint_declaration(&name_upper, category)); + let _: fmt::Result = writeln!(result, "{}", get_lint_declaration(&name_upper, category)); result.push_str(&if enable_msrv { formatdoc!( @@ -281,7 +321,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { }} // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed. - // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`. // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs` "# ) diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index dcd9a4adcbd46..4d5b3bf8a948d 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.74" +version = "0.1.75" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -28,6 +28,9 @@ semver = "1.0" rustc-semver = "1.1" url = "2.2" +[dev-dependencies] +walkdir = "2.3" + [features] deny-warnings = ["clippy_utils/deny-warnings"] # build clippy with internal lints enabled, off by default diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs index e1ef514edfd18..e3f4cf79d315c 100644 --- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/allow_attributes.rs @@ -8,6 +8,7 @@ use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { + /// ### What it does /// Checks for usage of the `#[allow]` attribute and suggests replacing it with /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) /// @@ -19,7 +20,6 @@ declare_clippy_lint! { /// (`#![allow]`) are usually used to enable or disable lints on a global scale. /// /// ### Why is this bad? - /// /// `#[expect]` attributes suppress the lint emission, but emit a warning, if /// the expectation is unfulfilled. This can be useful to be notified when the /// lint is no longer triggered. diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index a88f2b51c827e..db01ddbde04e3 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -183,7 +183,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for empty lines after documenation comments. + /// Checks for empty lines after documentation comments. /// /// ### Why is this bad? /// The documentation comment was most likely meant to be an inner attribute or regular comment. @@ -616,7 +616,7 @@ fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) { attr.span, "#[should_panic] attribute without a reason", "consider specifying the expected panic", - r#"#[should_panic(expected = /* panic message */)]"#.into(), + "#[should_panic(expected = /* panic message */)]".into(), Applicability::HasPlaceholders, ); } @@ -795,7 +795,7 @@ impl EarlyLintPass for EarlyAttributes { /// Check for empty lines after outer attributes. /// -/// Attributes and documenation comments are both considered outer attributes +/// Attributes and documentation comments are both considered outer attributes /// by the AST. However, the average user likely considers them to be different. /// Checking for empty lines after each of these attributes is split into two different /// lints but can share the same logic. diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index d40a385435afb..accff9b0a34c6 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{match_def_path, paths}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; -use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind}; +use rustc_hir::{AsyncGeneratorKind, Body, GeneratorKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::GeneratorInteriorTypeCause; +use rustc_middle::mir::GeneratorLayout; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; @@ -197,28 +197,35 @@ impl LateLintPass<'_> for AwaitHolding { fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { use AsyncGeneratorKind::{Block, Closure, Fn}; if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind { - let body_id = BodyId { - hir_id: body.value.hir_id, - }; - let typeck_results = cx.tcx.typeck_body(body_id); - self.check_interior_types( - cx, - typeck_results.generator_interior_types.as_ref().skip_binder(), - body.value.span, - ); + let def_id = cx.tcx.hir().body_owner_def_id(body.id()); + if let Some(generator_layout) = cx.tcx.mir_generator_witnesses(def_id) { + self.check_interior_types(cx, generator_layout); + } } } } impl AwaitHolding { - fn check_interior_types(&self, cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) { - for ty_cause in ty_causes { + fn check_interior_types(&self, cx: &LateContext<'_>, generator: &GeneratorLayout<'_>) { + for (ty_index, ty_cause) in generator.field_tys.iter_enumerated() { if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() { + let await_points = || { + generator + .variant_source_info + .iter_enumerated() + .filter_map(|(variant, source_info)| { + generator.variant_fields[variant] + .raw + .contains(&ty_index) + .then_some(source_info.span) + }) + .collect::>() + }; if is_mutex_guard(cx, adt.did()) { span_lint_and_then( cx, AWAIT_HOLDING_LOCK, - ty_cause.span, + ty_cause.source_info.span, "this `MutexGuard` is held across an `await` point", |diag| { diag.help( @@ -226,7 +233,7 @@ impl AwaitHolding { `MutexGuard` is dropped before calling await", ); diag.span_note( - ty_cause.scope_span.unwrap_or(span), + await_points(), "these are all the `await` points this lock is held through", ); }, @@ -235,18 +242,18 @@ impl AwaitHolding { span_lint_and_then( cx, AWAIT_HOLDING_REFCELL_REF, - ty_cause.span, + ty_cause.source_info.span, "this `RefCell` reference is held across an `await` point", |diag| { diag.help("ensure the reference is dropped before calling `await`"); diag.span_note( - ty_cause.scope_span.unwrap_or(span), + await_points(), "these are all the `await` points this reference is held through", ); }, ); } else if let Some(disallowed) = self.def_ids.get(&adt.did()) { - emit_invalid_type(cx, ty_cause.span, disallowed); + emit_invalid_type(cx, ty_cause.source_info.span, disallowed); } } } @@ -280,5 +287,5 @@ fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool { } fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool { - match_def_path(cx, def_id, &paths::REFCELL_REF) || match_def_path(cx, def_id, &paths::REFCELL_REFMUT) + matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RefCellRef | sym::RefCellRefMut)) } diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs index fa9c525fc08d9..3f1ff66b8cf60 100644 --- a/src/tools/clippy/clippy_lints/src/box_default.rs +++ b/src/tools/clippy/clippy_lints/src/box_default.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; use clippy_utils::ty::expr_sig; -use clippy_utils::{get_parent_node, is_default_equivalent, match_path, path_def_id, paths}; +use clippy_utils::{get_parent_node, is_default_equivalent, path_def_id}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_ty, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind}; +use rustc_hir::{def::Res, Block, Expr, ExprKind, Local, Node, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -55,7 +55,7 @@ impl LateLintPass<'_> for BoxDefault { expr.span, "`Box::new(_)` of default value", "try", - if is_plain_default(arg_path) || given_type(cx, expr) { + if is_plain_default(cx, arg_path) || given_type(cx, expr) { "Box::default()".into() } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) @@ -68,11 +68,13 @@ impl LateLintPass<'_> for BoxDefault { } } -fn is_plain_default(arg_path: &Expr<'_>) -> bool { +fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool { // we need to match the actual path so we don't match e.g. "u8::default" - if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind { + if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind + && let Res::Def(_, def_id) = path.res + { // avoid generic parameters - match_path(path, &paths::DEFAULT_TRAIT_METHOD) && path.segments.iter().all(|seg| seg.args.is_none()) + cx.tcx.is_diagnostic_item(sym::default_fn, def_id) && path.segments.iter().all(|seg| seg.args.is_none()) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index cf07e050ccce9..c586b572be9a1 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -25,7 +25,7 @@ pub(super) fn check( // The suggestion is to use a function call, so if the original expression // has parens on the outside, they are no longer needed. let mut applicability = Applicability::MachineApplicable; - let opt = snippet_opt(cx, cast_op.span); + let opt = snippet_opt(cx, cast_op.span.source_callsite()); let sugg = opt.as_ref().map_or_else( || { applicability = Applicability::HasPlaceholders; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 84b99ad5c243d..f99a51e2b88c5 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -44,7 +44,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b .unwrap_or(u64::max_value()) .min(apply_reductions(cx, nbits, left, signed)), BinOpKind::Shr => apply_reductions(cx, nbits, left, signed) - .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))), + .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).unwrap_or_default())), _ => nbits, }, ExprKind::MethodCall(method, left, [right], _) => { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index 1de69122101c5..9e8ef28253741 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_c_void; -use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, match_any_def_paths, paths}; +use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant}; use rustc_hir::{Expr, ExprKind, GenericArg}; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; @@ -75,16 +75,17 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { } }, ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => { - static PATHS: &[&[&str]] = &[ - paths::PTR_READ_UNALIGNED.as_slice(), - paths::PTR_UNALIGNED_VOLATILE_LOAD.as_slice(), - paths::PTR_UNALIGNED_VOLATILE_STORE.as_slice(), - ]; - if let ExprKind::Path(path) = &func.kind && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() - && (match_any_def_paths(cx, def_id, PATHS).is_some() - || cx.tcx.is_diagnostic_item(sym::ptr_write_unaligned, def_id)) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some( + sym::ptr_write_unaligned + | sym::ptr_read_unaligned + | sym::intrinsics_unaligned_volatile_load + | sym::intrinsics_unaligned_volatile_store + ) + ) { true } else { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index 5e0123842b041..eb0f75b2f605b 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; -use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; +use rustc_span::sym; use super::CAST_SLICE_FROM_RAW_PARTS; @@ -17,12 +17,10 @@ enum RawPartsKind { } fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option { - if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS) { - Some(RawPartsKind::Immutable) - } else if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS_MUT) { - Some(RawPartsKind::Mutable) - } else { - None + match cx.tcx.get_diagnostic_name(did)? { + sym::slice_from_raw_parts => Some(RawPartsKind::Immutable), + sym::slice_from_raw_parts_mut => Some(RawPartsKind::Mutable), + _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index 88ffbb55486bd..b00130ffd76db 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -20,6 +20,7 @@ mod ptr_as_ptr; mod ptr_cast_constness; mod unnecessary_cast; mod utils; +mod zero_ptr; use clippy_utils::is_hir_ty_cfg_dependant; use clippy_utils::msrvs::{self, Msrv}; @@ -665,6 +666,29 @@ declare_clippy_lint! { "casting a known floating-point NaN into an integer" } +declare_clippy_lint! { + /// ### What it does + /// Catch casts from `0` to some pointer type + /// + /// ### Why is this bad? + /// This generally means `null` and is better expressed as + /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}. + /// + /// ### Example + /// ```rust + /// let a = 0 as *const u32; + /// ``` + /// + /// Use instead: + /// ```rust + /// let a = std::ptr::null::(); + /// ``` + #[clippy::version = "pre 1.29.0"] + pub ZERO_PTR, + style, + "using `0 as *{const, mut} T`" +} + pub struct Casts { msrv: Msrv, } @@ -699,6 +723,7 @@ impl_lint_pass!(Casts => [ CAST_SLICE_FROM_RAW_PARTS, AS_PTR_CAST_MUT, CAST_NAN_TO_INT, + ZERO_PTR, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -729,6 +754,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to); + zero_ptr::check(cx, expr, cast_expr, cast_to_hir); if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) { cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span); diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs new file mode 100644 index 0000000000000..5071af5ecb986 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs @@ -0,0 +1,39 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use clippy_utils::{in_constant, is_integer_literal, std_or_core}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability, Ty, TyKind}; +use rustc_lint::LateContext; + +use super::ZERO_PTR; + +pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) { + if let TyKind::Ptr(ref mut_ty) = to.kind + && is_integer_literal(from, 0) + && !in_constant(cx, from.hir_id) + && let Some(std_or_core) = std_or_core(cx) + { + let (msg, sugg_fn) = match mut_ty.mutbl { + Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"), + Mutability::Not => ("`0 as *const _` detected", "ptr::null"), + }; + + let sugg = if let TyKind::Infer = mut_ty.ty.kind { + format!("{std_or_core}::{sugg_fn}()") + } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) { + format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") + } else { + return; + }; + + span_lint_and_sugg( + cx, + ZERO_PTR, + expr.span, + msg, + "try", + sugg, + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs index 878248a6bdc8c..2bca695c43b15 100644 --- a/src/tools/clippy/clippy_lints/src/create_dir.rs +++ b/src/tools/clippy/clippy_lints/src/create_dir.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -37,7 +37,7 @@ impl LateLintPass<'_> for CreateDir { if let ExprKind::Call(func, [arg, ..]) = expr.kind; if let ExprKind::Path(ref path) = func.kind; if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR); + if cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id); then { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index a4d40df52e7bc..481c44031cf72 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -97,6 +97,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::casts::PTR_AS_PTR_INFO, crate::casts::PTR_CAST_CONSTNESS_INFO, crate::casts::UNNECESSARY_CAST_INFO, + crate::casts::ZERO_PTR_INFO, crate::checked_conversions::CHECKED_CONVERSIONS_INFO, crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO, crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO, @@ -228,6 +229,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO, crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO, crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO, + crate::iter_without_into_iter::INTO_ITER_WITHOUT_ITER_INFO, + crate::iter_without_into_iter::ITER_WITHOUT_INTO_ITER_INFO, crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO, crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO, crate::large_futures::LARGE_FUTURES_INFO, @@ -279,6 +282,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_clamp::MANUAL_CLAMP_INFO, crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, + crate::manual_hash_one::MANUAL_HASH_ONE_INFO, crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO, crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, @@ -399,9 +403,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::OR_FUN_CALL_INFO, crate::methods::OR_THEN_UNWRAP_INFO, crate::methods::PATH_BUF_PUSH_OVERWRITE_INFO, + crate::methods::PATH_ENDS_WITH_EXT_INFO, crate::methods::RANGE_ZIP_WITH_LEN_INFO, crate::methods::READONLY_WRITE_LOCK_INFO, crate::methods::READ_LINE_WITHOUT_TRIM_INFO, + crate::methods::REDUNDANT_AS_STR_INFO, crate::methods::REPEAT_ONCE_INFO, crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO, crate::methods::SEARCH_IS_SOME_INFO, @@ -441,7 +447,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::misc::SHORT_CIRCUIT_STATEMENT_INFO, crate::misc::TOPLEVEL_REF_ARG_INFO, crate::misc::USED_UNDERSCORE_BINDING_INFO, - crate::misc::ZERO_PTR_INFO, crate::misc_early::BUILTIN_TYPE_SHADOW_INFO, crate::misc_early::DOUBLE_NEG_INFO, crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO, @@ -479,6 +484,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_bool::NEEDLESS_BOOL_INFO, crate::needless_bool::NEEDLESS_BOOL_ASSIGN_INFO, crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO, + crate::needless_borrows_for_generic_args::NEEDLESS_BORROWS_FOR_GENERIC_ARGS_INFO, crate::needless_continue::NEEDLESS_CONTINUE_INFO, crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, @@ -671,6 +677,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO, crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO, crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO, + crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO, crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO, crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO, crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 763ad0264ad91..5787f19cc6cb1 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -1,9 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{has_drop, is_copy}; -use clippy_utils::{ - any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths, -}; +use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -14,7 +12,7 @@ use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -91,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); + if cx.tcx.is_diagnostic_item(sym::default_fn, def_id); if !is_update_syntax_base(cx, expr); // Detect and ignore ::default() because these calls do explicitly name the type. if let QPath::Resolved(None, _path) = qpath; @@ -268,7 +266,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); then { // right hand side of assignment is `Default::default` - match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD) + cx.tcx.is_diagnostic_item(sym::default_fn, def_id) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs index a294c69378774..0676777e79681 100644 --- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs +++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{is_ty_alias, match_def_path, paths}; +use clippy_utils::is_ty_alias; use hir::def::Res; use hir::ExprKind; use rustc_errors::Applicability; @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -63,7 +64,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs { // `::Assoc` cannot be used as a constructor if !is_alias(*base); if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); - if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); + if cx.tcx.is_diagnostic_item(sym::default_fn, def_id); // make sure we have a struct with no fields (unit struct) if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); if def.is_struct(); diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs index 572990aaba109..3d6d257e386b5 100644 --- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use clippy_utils::{last_path_segment, match_def_path, paths}; +use clippy_utils::last_path_segment; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::SyntaxContext; +use rustc_span::{sym, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -37,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { && let TyKind::Path(ty_path) = &ty.kind && let QPath::Resolved(None, path) = ty_path && let def::Res::Def(_, def_id) = &path.res - && match_def_path(cx, *def_id, &paths::ITER_EMPTY) + && cx.tcx.is_diagnostic_item(sym::IterEmpty, *def_id) && let ctxt = expr.span.ctxt() && ty.span.ctxt() == ctxt { diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index bbce6e1dd8f2b..63ec819502088 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_help; -use rustc_hir::{self as hir, HirId, Item, ItemKind}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, FieldDef, GenericArg, List}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -52,7 +52,10 @@ declare_lint_pass!(DefaultUnionRepresentation => [DEFAULT_UNION_REPRESENTATION]) impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if is_union_with_two_non_zst_fields(cx, item) && !has_c_repr_attr(cx, item.hir_id()) { + if !item.span.from_expansion() + && is_union_with_two_non_zst_fields(cx, item) + && !has_c_repr_attr(cx, item.hir_id()) + { span_lint_and_help( cx, DEFAULT_UNION_REPRESENTATION, @@ -73,18 +76,17 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { /// if there is only one field left after ignoring ZST fields then the offset /// of that field does not matter either.) fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool { - if let ItemKind::Union(data, _) = &item.kind { - data.fields().iter().filter(|f| !is_zst(cx, f.ty)).count() >= 2 + if let ItemKind::Union(..) = &item.kind + && let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() + { + adt_def.all_fields().filter(|f| !is_zst(cx, f, args)).count() >= 2 } else { false } } -fn is_zst(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) -> bool { - if hir_ty.span.from_expansion() { - return false; - } - let ty = hir_ty_to_ty(cx.tcx, hir_ty); +fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: &'tcx List>) -> bool { + let ty = field.ty(cx.tcx, args); if let Ok(layout) = cx.layout_of(ty) { layout.is_zst() } else { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 8090f821d1ff2..14877385646a0 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1,41 +1,24 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; -use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap}; -use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::ty::{implements_trait, is_copy, peel_mid_ty_refs}; +use clippy_utils::ty::{implements_trait, peel_mid_ty_refs}; use clippy_utils::{ expr_use_ctxt, get_parent_expr, get_parent_node, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode, }; - -use hir::def::DefKind; -use hir::MatchSource; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch}; use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{ - self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, - Path, QPath, TyKind, UnOp, + self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, + Pat, PatKind, Path, QPath, TyKind, UnOp, }; -use rustc_index::bit_set::BitSet; -use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{ - self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, List, ParamEnv, ParamTy, ProjectionPredicate, Ty, - TyCtxt, TypeVisitableExt, TypeckResults, -}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_trait_selection::traits::{Obligation, ObligationCause}; -use std::collections::VecDeque; declare_clippy_lint! { /// ### What it does @@ -183,24 +166,6 @@ pub struct Dereferencing<'tcx> { /// /// e.g. `m!(x) | Foo::Bar(ref x)` ref_locals: FxIndexMap>, - - /// Stack of (body owner, `PossibleBorrowerMap`) pairs. Used by - /// `needless_borrow_impl_arg_position` to determine when a borrowed expression can instead - /// be moved. - possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, - - // `IntoIterator` for arrays requires Rust 1.53. - msrv: Msrv, -} - -impl<'tcx> Dereferencing<'tcx> { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { - msrv, - ..Dereferencing::default() - } - } } #[derive(Debug)] @@ -355,52 +320,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { )); }, (Some(use_cx), RefOp::AddrOf(mutability)) => { - let defined_ty = use_cx.node.defined_ty(cx); - - // Check needless_borrow for generic arguments. - if !use_cx.is_ty_unified - && let Some(DefinedTy::Mir(ty)) = defined_ty - && let ty::Param(ty) = *ty.value.skip_binder().kind() - && let Some((hir_id, fn_id, i)) = match use_cx.node { - ExprUseNode::MethodArg(_, _, 0) => None, - ExprUseNode::MethodArg(hir_id, None, i) => { - typeck.type_dependent_def_id(hir_id).map(|id| (hir_id, id, i)) - }, - ExprUseNode::FnArg(&Expr { kind: ExprKind::Path(ref p), hir_id, .. }, i) - if !path_has_args(p) => match typeck.qpath_res(p, hir_id) { - Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) => { - Some((hir_id, id, i)) - }, - _ => None, - }, - _ => None, - } && let count = needless_borrow_generic_arg_count( - cx, - &mut self.possible_borrowers, - fn_id, - typeck.node_args(hir_id), - i, - ty, - expr, - &self.msrv, - ) && count != 0 - { - self.state = Some(( - State::DerefedBorrow(DerefedBorrow { - count: count - 1, - msg: "the borrowed expression implements the required traits", - stability: TyCoercionStability::None, - for_field_access: None, - }), - StateData { - span: expr.span, - hir_id: expr.hir_id, - adjusted_ty: use_cx.adjustments.last().map_or(expr_ty, |a| a.target), - }, - )); - return; - } - // Find the number of times the borrow is auto-derefed. let mut iter = use_cx.adjustments.iter(); let mut deref_count = 0usize; @@ -419,7 +338,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { }; }; - let stability = defined_ty.map_or(TyCoercionStability::None, |ty| { + let stability = use_cx.node.defined_ty(cx).map_or(TyCoercionStability::None, |ty| { TyCoercionStability::for_defined_ty(cx, ty, use_cx.node.is_return()) }); let can_auto_borrow = match use_cx.node { @@ -700,12 +619,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { } fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { - if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| { - local_def_id == cx.tcx.hir().body_owner_def_id(body.id()) - }) { - self.possible_borrowers.pop(); - } - if Some(body.id()) == self.current_body { for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) { let replacements = pat.replacements; @@ -729,8 +642,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { self.current_body = None; } } - - extract_msrv_attr!(LateContext); } fn try_parse_ref_op<'tcx>( @@ -788,13 +699,6 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { } } -fn path_has_args(p: &QPath<'_>) -> bool { - match *p { - QPath::Resolved(_, Path { segments: [.., s], .. }) | QPath::TypeRelative(_, s) => s.args.is_some(), - _ => false, - } -} - fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { if let Some(parent) = get_parent_expr(cx, e) && parent.span.ctxt() == e.span.ctxt() @@ -940,7 +844,6 @@ impl TyCoercionStability { | ty::FnDef(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Closure(..) | ty::Never | ty::Tuple(_) @@ -981,274 +884,6 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool { v.0 } -/// Checks for the number of borrow expressions which can be removed from the given expression -/// where the expression is used as an argument to a function expecting a generic type. -/// -/// The following constraints will be checked: -/// * The borrowed expression meets all the generic type's constraints. -/// * The generic type appears only once in the functions signature. -/// * The borrowed value will not be moved if it is used later in the function. -#[expect(clippy::too_many_arguments)] -fn needless_borrow_generic_arg_count<'tcx>( - cx: &LateContext<'tcx>, - possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, - fn_id: DefId, - callee_args: &'tcx List>, - arg_index: usize, - param_ty: ParamTy, - mut expr: &Expr<'tcx>, - msrv: &Msrv, -) -> usize { - let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait(); - let sized_trait_def_id = cx.tcx.lang_items().sized_trait(); - - let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder(); - let predicates = cx.tcx.param_env(fn_id).caller_bounds(); - let projection_predicates = predicates - .iter() - .filter_map(|predicate| { - if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() { - Some(projection_predicate) - } else { - None - } - }) - .collect::>(); - - let mut trait_with_ref_mut_self_method = false; - - // If no traits were found, or only the `Destruct`, `Sized`, or `Any` traits were found, return. - if predicates - .iter() - .filter_map(|predicate| { - if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() - && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) - { - Some(trait_predicate.trait_ref.def_id) - } else { - None - } - }) - .inspect(|trait_def_id| { - trait_with_ref_mut_self_method |= has_ref_mut_self_method(cx, *trait_def_id); - }) - .all(|trait_def_id| { - Some(trait_def_id) == destruct_trait_def_id - || Some(trait_def_id) == sized_trait_def_id - || cx.tcx.is_diagnostic_item(sym::Any, trait_def_id) - }) - { - return 0; - } - - // See: - // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1289294201 - // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1292225232 - if projection_predicates - .iter() - .any(|projection_predicate| is_mixed_projection_predicate(cx, fn_id, projection_predicate)) - { - return 0; - } - - // `args_with_referent_ty` can be constructed outside of `check_referent` because the same - // elements are modified each time `check_referent` is called. - let mut args_with_referent_ty = callee_args.to_vec(); - - let mut check_reference_and_referent = |reference, referent| { - let referent_ty = cx.typeck_results().expr_ty(referent); - - if !is_copy(cx, referent_ty) - && (referent_ty.has_significant_drop(cx.tcx, cx.param_env) - || !referent_used_exactly_once(cx, possible_borrowers, reference)) - { - return false; - } - - // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 - if trait_with_ref_mut_self_method && !matches!(referent_ty.kind(), ty::Ref(_, _, Mutability::Mut)) { - return false; - } - - if !replace_types( - cx, - param_ty, - referent_ty, - fn_sig, - arg_index, - &projection_predicates, - &mut args_with_referent_ty, - ) { - return false; - } - - predicates.iter().all(|predicate| { - if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() - && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) - && let ty::Param(param_ty) = trait_predicate.self_ty().kind() - && let GenericArgKind::Type(ty) = args_with_referent_ty[param_ty.index as usize].unpack() - && ty.is_array() - && !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) - { - return false; - } - - let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty); - let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); - let infcx = cx.tcx.infer_ctxt().build(); - infcx.predicate_must_hold_modulo_regions(&obligation) - }) - }; - - let mut count = 0; - while let ExprKind::AddrOf(_, _, referent) = expr.kind { - if !check_reference_and_referent(expr, referent) { - break; - } - expr = referent; - count += 1; - } - count -} - -fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool { - cx.tcx - .associated_items(trait_def_id) - .in_definition_order() - .any(|assoc_item| { - if assoc_item.fn_has_self_parameter { - let self_ty = cx - .tcx - .fn_sig(assoc_item.def_id) - .instantiate_identity() - .skip_binder() - .inputs()[0]; - matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Mut)) - } else { - false - } - }) -} - -fn is_mixed_projection_predicate<'tcx>( - cx: &LateContext<'tcx>, - callee_def_id: DefId, - projection_predicate: &ProjectionPredicate<'tcx>, -) -> bool { - let generics = cx.tcx.generics_of(callee_def_id); - // The predicate requires the projected type to equal a type parameter from the parent context. - if let Some(term_ty) = projection_predicate.term.ty() - && let ty::Param(term_param_ty) = term_ty.kind() - && (term_param_ty.index as usize) < generics.parent_count - { - // The inner-most self type is a type parameter from the current function. - let mut projection_ty = projection_predicate.projection_ty; - loop { - match projection_ty.self_ty().kind() { - ty::Alias(ty::Projection, inner_projection_ty) => { - projection_ty = *inner_projection_ty; - } - ty::Param(param_ty) => { - return (param_ty.index as usize) >= generics.parent_count; - } - _ => { - return false; - } - } - } - } else { - false - } -} - -fn referent_used_exactly_once<'tcx>( - cx: &LateContext<'tcx>, - possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, - reference: &Expr<'tcx>, -) -> bool { - if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id) - && let Some(local) = expr_local(cx.tcx, reference) - && let [location] = *local_assignments(mir, local).as_slice() - && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index) - && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind - && !place.is_indirect_first_projection() - // Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710) - && TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none() - { - let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); - if possible_borrowers - .last() - .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id) - { - possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); - } - let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1; - // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is - // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of - // itself. See the comment in that method for an explanation as to why. - possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location) - && used_exactly_once(mir, place.local).unwrap_or(false) - } else { - false - } -} - -// Iteratively replaces `param_ty` with `new_ty` in `args`, and similarly for each resulting -// projected type that is a type parameter. Returns `false` if replacing the types would have an -// effect on the function signature beyond substituting `new_ty` for `param_ty`. -// See: https://github.com/rust-lang/rust-clippy/pull/9136#discussion_r927212757 -fn replace_types<'tcx>( - cx: &LateContext<'tcx>, - param_ty: ParamTy, - new_ty: Ty<'tcx>, - fn_sig: FnSig<'tcx>, - arg_index: usize, - projection_predicates: &[ProjectionPredicate<'tcx>], - args: &mut [ty::GenericArg<'tcx>], -) -> bool { - let mut replaced = BitSet::new_empty(args.len()); - - let mut deque = VecDeque::with_capacity(args.len()); - deque.push_back((param_ty, new_ty)); - - while let Some((param_ty, new_ty)) = deque.pop_front() { - // If `replaced.is_empty()`, then `param_ty` and `new_ty` are those initially passed in. - if !fn_sig - .inputs_and_output - .iter() - .enumerate() - .all(|(i, ty)| (replaced.is_empty() && i == arg_index) || !ty.contains(param_ty.to_ty(cx.tcx))) - { - return false; - } - - args[param_ty.index as usize] = ty::GenericArg::from(new_ty); - - // The `replaced.insert(...)` check provides some protection against infinite loops. - if replaced.insert(param_ty.index) { - for projection_predicate in projection_predicates { - if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx) - && let Some(term_ty) = projection_predicate.term.ty() - && let ty::Param(term_param_ty) = term_ty.kind() - { - let projection = cx.tcx.mk_ty_from_kind(ty::Alias( - ty::Projection, - projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty), - )); - - if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) - && args[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty) - { - deque.push_back((*term_param_ty, projected_ty)); - } - } - } - } - } - - true -} - fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool { if let ty::Adt(adt, _) = *ty.kind() { adt.is_struct() && adt.all_fields().any(|f| f.name == name) diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index bf2add6aa64f7..e789e0da6797a 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -459,7 +459,7 @@ struct Fragments<'a> { impl Fragments<'_> { fn span(self, cx: &LateContext<'_>, range: Range) -> Option { - source_span_for_markdown_range(cx.tcx, &self.doc, &range, &self.fragments) + source_span_for_markdown_range(cx.tcx, self.doc, &range, self.fragments) } } @@ -513,6 +513,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"]; +#[allow(clippy::too_many_lines)] // Only a big match statement fn check_doc<'a, Events: Iterator, Range)>>( cx: &LateContext<'_>, valid_idents: &FxHashSet, diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 96c5c7fc50931..646767868e2cf 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -1,7 +1,7 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` -use clippy_utils::consts::{miri_to_const, Constant}; +use clippy_utils::consts::{mir_to_const, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -50,8 +50,8 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .tcx .const_eval_poly(def_id.to_def_id()) .ok() - .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty)); - if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) { + .map(|val| rustc_middle::mir::Const::from_value(val, ty)); + if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx, c)) { if let ty::Adt(adt, _) = ty.kind() { if adt.is_enum() { ty = adt.repr().discr_type().to_ty(cx.tcx); diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index d4df6f7aa2d09..e332f681b6dbd 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -167,7 +167,10 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n return; } - let first = &def.variants[0].ident.name.as_str(); + let first = match def.variants.first() { + Some(variant) => variant.ident.name.as_str(), + None => return, + }; let mut pre = camel_case_split(first); let mut post = pre.clone(); post.reverse(); diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs index 379af9b2234c2..6d429fbd03538 100644 --- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs +++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs @@ -3,7 +3,6 @@ use clippy_utils::path_res; use clippy_utils::ty::implements_trait; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{Item, ItemKind}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Visibility; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -28,7 +27,7 @@ declare_clippy_lint! { /// /// impl std::error::Error for Error { ... } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub ERROR_IMPL_ERROR, restriction, "exported types named `Error` that implement `Error`" @@ -42,9 +41,10 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError { }; match item.kind { - ItemKind::TyAlias(ty, _) if implements_trait(cx, hir_ty_to_ty(cx.tcx, ty), error_def_id, &[]) - && item.ident.name == sym::Error - && is_visible_outside_module(cx, item.owner_id.def_id) => + ItemKind::TyAlias(..) if item.ident.name == sym::Error + && is_visible_outside_module(cx, item.owner_id.def_id) + && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() + && implements_trait(cx, ty, error_def_id, &[]) => { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 8ba6a9e48763f..5de79133c7dcc 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_entrypoint_fn, match_def_path, paths}; +use clippy_utils::{is_entrypoint_fn}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -45,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { if let ExprKind::Call(path_expr, _args) = e.kind; if let ExprKind::Path(ref path) = path_expr.kind; if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::EXIT); + if cx.tcx.is_diagnostic_item(sym::process_exit, def_id); let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id; if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent); // If the next item up is a function we check if it is an entry point diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index 4b9ca8c917e52..6f6177340f487 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::{find_format_args, format_args_inputs_span}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{is_expn_of, match_function_call, paths}; +use clippy_utils::{is_expn_of, path_def_id}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -47,64 +47,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind && unwrap_fun.ident.name == sym::unwrap // match call to write_fmt - && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind) + && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind) + && let ExprKind::Call(write_recv_path, _) = write_recv.kind && write_fun.ident.name == sym!(write_fmt) + && let Some(def_id) = path_def_id(cx, write_recv_path) + { // match calls to std::io::stdout() / std::io::stderr () - && let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() { - Some("stdout") - } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() { - Some("stderr") + let (dest_name, prefix) = match cx.tcx.get_diagnostic_name(def_id) { + Some(sym::io_stdout) => ("stdout", ""), + Some(sym::io_stderr) => ("stderr", "e"), + _ => return, + }; + let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { return; }; + + // ordering is important here, since `writeln!` uses `write!` internally + let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() { + Some("writeln") + } else if is_expn_of(write_call.span, "write").is_some() { + Some("write") } else { None - } - { - find_format_args(cx, write_arg, ExpnId::root(), |format_args| { - let calling_macro = - // ordering is important here, since `writeln!` uses `write!` internally - if is_expn_of(write_call.span, "writeln").is_some() { - Some("writeln") - } else if is_expn_of(write_call.span, "write").is_some() { - Some("write") - } else { - None - }; - let prefix = if dest_name == "stderr" { - "e" - } else { - "" - }; + }; - // We need to remove the last trailing newline from the string because the - // underlying `fmt::write` function doesn't know whether `println!` or `print!` was - // used. - let (used, sugg_mac) = if let Some(macro_name) = calling_macro { - ( - format!("{macro_name}!({dest_name}(), ...)"), - macro_name.replace("write", "print"), - ) - } else { - ( - format!("{dest_name}().write_fmt(...)"), - "print".into(), - ) - }; - let mut applicability = Applicability::MachineApplicable; - let inputs_snippet = snippet_with_applicability( - cx, - format_args_inputs_span(format_args), - "..", - &mut applicability, - ); - span_lint_and_sugg( - cx, - EXPLICIT_WRITE, - expr.span, - &format!("use of `{used}.unwrap()`"), - "try", - format!("{prefix}{sugg_mac}!({inputs_snippet})"), - applicability, - ); - }); + // We need to remove the last trailing newline from the string because the + // underlying `fmt::write` function doesn't know whether `println!` or `print!` was + // used. + let (used, sugg_mac) = if let Some(macro_name) = calling_macro { + ( + format!("{macro_name}!({dest_name}(), ...)"), + macro_name.replace("write", "print"), + ) + } else { + ( + format!("{dest_name}().write_fmt(...)"), + "print".into(), + ) + }; + let mut applicability = Applicability::MachineApplicable; + let inputs_snippet = snippet_with_applicability( + cx, + format_args_inputs_span(&format_args), + "..", + &mut applicability, + ); + span_lint_and_sugg( + cx, + EXPLICIT_WRITE, + expr.span, + &format!("use of `{used}.unwrap()`"), + "try", + format!("{prefix}{sugg_mac}!({inputs_snippet})"), + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index c18006a71c26e..0a885984abbf2 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -246,8 +246,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { { self.ty_params.remove(&def_id); } + } else { + // If the bounded type isn't a generic param, but is instead a concrete generic + // type, any params we find nested inside of it are being used as concrete types, + // and can therefore can be considered used. So, we're fine to walk the left-hand + // side of the where bound. + walk_ty(self, predicate.bounded_ty); } - // Only walk the right-hand side of where bounds for bound in predicate.bounds { walk_param_bound(self, bound); } diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index f4f8bdc2c44e5..b748d32936792 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -43,14 +43,10 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]); impl<'tcx> LateLintPass<'tcx> for UselessFormat { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let Some(macro_call) = root_macro_call_first_node(cx, expr) else { - return; - }; - if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) { - return; - } - - find_format_args(cx, expr, macro_call.expn, |format_args| { + if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) + && let Some(format_args) = find_format_args(cx, expr, macro_call.expn) + { let mut applicability = Applicability::MachineApplicable; let call_site = macro_call.span; @@ -91,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { }, _ => {}, } - }); + } } } diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 01c714c414b5a..39abf5c2def56 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -186,15 +186,10 @@ impl FormatArgs { impl<'tcx> LateLintPass<'tcx> for FormatArgs { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - let Some(macro_call) = root_macro_call_first_node(cx, expr) else { - return; - }; - if !is_format_macro(cx, macro_call.def_id) { - return; - } - let name = cx.tcx.item_name(macro_call.def_id); - - find_format_args(cx, expr, macro_call.expn, |format_args| { + if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && is_format_macro(cx, macro_call.def_id) + && let Some(format_args) = find_format_args(cx, expr, macro_call.expn) + { for piece in &format_args.template { if let FormatArgsPiece::Placeholder(placeholder) = piece && let Ok(index) = placeholder.argument.index @@ -206,12 +201,13 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { if placeholder.format_trait != FormatTrait::Display || placeholder.format_options != FormatOptions::default() - || is_aliased(format_args, index) + || is_aliased(&format_args, index) { continue; } if let Ok(arg_hir_expr) = arg_expr { + let name = cx.tcx.item_name(macro_call.def_id); check_format_in_format_args(cx, macro_call.span, name, arg_hir_expr); check_to_string_in_format_args(cx, name, arg_hir_expr); } @@ -219,9 +215,9 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { } if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) { - check_uninlined_args(cx, format_args, macro_call.span, macro_call.def_id, self.ignore_mixed); + check_uninlined_args(cx, &format_args, macro_call.span, macro_call.def_id, self.ignore_mixed); } - }); + } } extract_msrv_attr!(LateContext); diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index 76369bccf9e3b..1d2f7cb71303b 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -170,30 +170,29 @@ fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, if let Some(outer_macro) = root_macro_call_first_node(cx, expr) && let macro_def_id = outer_macro.def_id && is_format_macro(cx, macro_def_id) + && let Some(format_args) = find_format_args(cx, expr, outer_macro.expn) { - find_format_args(cx, expr, outer_macro.expn, |format_args| { - for piece in &format_args.template { - if let FormatArgsPiece::Placeholder(placeholder) = piece - && let trait_name = match placeholder.format_trait { - FormatTrait::Display => sym::Display, - FormatTrait::Debug => sym::Debug, - FormatTrait::LowerExp => sym!(LowerExp), - FormatTrait::UpperExp => sym!(UpperExp), - FormatTrait::Octal => sym!(Octal), - FormatTrait::Pointer => sym::Pointer, - FormatTrait::Binary => sym!(Binary), - FormatTrait::LowerHex => sym!(LowerHex), - FormatTrait::UpperHex => sym!(UpperHex), - } - && trait_name == impl_trait.name - && let Ok(index) = placeholder.argument.index - && let Some(arg) = format_args.arguments.all_args().get(index) - && let Ok(arg_expr) = find_format_arg_expr(expr, arg) - { - check_format_arg_self(cx, expr.span, arg_expr, impl_trait); + for piece in &format_args.template { + if let FormatArgsPiece::Placeholder(placeholder) = piece + && let trait_name = match placeholder.format_trait { + FormatTrait::Display => sym::Display, + FormatTrait::Debug => sym::Debug, + FormatTrait::LowerExp => sym!(LowerExp), + FormatTrait::UpperExp => sym!(UpperExp), + FormatTrait::Octal => sym!(Octal), + FormatTrait::Pointer => sym::Pointer, + FormatTrait::Binary => sym!(Binary), + FormatTrait::LowerHex => sym!(LowerHex), + FormatTrait::UpperHex => sym!(UpperHex), } + && trait_name == impl_trait.name + && let Ok(index) = placeholder.argument.index + && let Some(arg) = format_args.arguments.all_args().get(index) + && let Ok(arg_expr) = find_format_arg_expr(expr, arg) + { + check_format_arg_self(cx, expr.span, arg_expr, impl_trait); } - }); + } } } diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs index 419c77343441c..0ec52f89e7166 100644 --- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs +++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs @@ -28,7 +28,7 @@ declare_clippy_lint! { /// // ... /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub FOUR_FORWARD_SLASHES, suspicious, "comments with 4 forward slashes (`////`) likely intended to be doc comments (`///`)" diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs index 5e859d97c6242..d82ea6d2fc80e 100644 --- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_c_void; -use clippy_utils::{match_def_path, path_def_id, paths}; +use clippy_utils::path_def_id; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; @@ -68,7 +68,7 @@ fn def_id_matches_type(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static s } } - if match_def_path(cx, def_id, &paths::WEAK_RC) || match_def_path(cx, def_id, &paths::WEAK_ARC) { + if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RcWeak | sym::ArcWeak)) { Some("Weak") } else { None diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs index d8ead1c9d9f68..ef2a66d4a209a 100644 --- a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs @@ -37,6 +37,10 @@ declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]); impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) { + if pat.span.from_expansion() { + return; + } + match cx.tcx.hir().get_parent(pat.hir_id) { Node::Param(param) if matches!(cx.tcx.hir().get_parent(param.hir_id), Node::Item(_)) => { // Ignore function parameters diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 64a4a3fa741bc..2b2ea156cd4d3 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -6,9 +6,8 @@ use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor}; use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; use rustc_hir_analysis::hir_ty_to_ty; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{Ty, TypeckResults}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -162,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { vis.visit_ty(ty); for target in &vis.found { - if in_external_macro(cx.sess(), generics.span) { + if generics.span.from_expansion() { continue; } let generics_suggestion_span = generics.span.substitute_dummy({ diff --git a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs index b00fa104f9825..f95d2c2edb1ef 100644 --- a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs +++ b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs @@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for NumberedFields { && fields .iter() .all(|f| f.ident.as_str().as_bytes().iter().all(u8::is_ascii_digit)) - && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias { .. }, ..)) + && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias, ..)) { let expr_spans = fields .iter() diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs index 8df7dfb8b9e5a..a1a115f6d79f6 100644 --- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs +++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs @@ -130,11 +130,7 @@ fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool { fn is_an_instant(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let expr_ty = cx.typeck_results().expr_ty(expr); - - match expr_ty.kind() { - rustc_middle::ty::Adt(def, _) => clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT), - _ => false, - } + ty::is_type_diagnostic_item(cx, expr_ty, sym::Instant) } fn is_a_duration(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 55a43e9156282..41477242bcc0b 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -1,10 +1,12 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_from_proc_macro, is_in_cfg_test}; -use rustc_hir::{HirId, ItemId, ItemKind, Mod}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::source::snippet_opt; +use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; +use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_hir::{HirId, Item, ItemKind, Mod}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{sym, Span}; +use rustc_span::hygiene::AstPass; +use rustc_span::{sym, ExpnKind}; declare_clippy_lint! { /// ### What it does @@ -41,46 +43,72 @@ declare_clippy_lint! { declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]); -impl LateLintPass<'_> for ItemsAfterTestModule { - fn check_mod(&mut self, cx: &LateContext<'_>, _: &Mod<'_>, _: HirId) { - let mut was_test_mod_visited = false; - let mut test_mod_span: Option = None; +fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { + if let ItemKind::Mod(test_mod) = item.kind + && item.span.hi() == test_mod.spans.inner_span.hi() + && is_cfg_test(cx.tcx, item.hir_id()) + && !item.span.from_expansion() + && !is_from_proc_macro(cx, item) + { + true + } else { + false + } +} - let hir = cx.tcx.hir(); - let items = hir.items().collect::>(); +impl LateLintPass<'_> for ItemsAfterTestModule { + fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: HirId) { + let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id)); - for (i, itid) in items.iter().enumerate() { - let item = hir.item(*itid); + let Some((mod_pos, test_mod)) = items.by_ref().enumerate().find(|(_, item)| cfg_test_module(cx, item)) else { + return; + }; - if_chain! { - if was_test_mod_visited; - if i == (items.len() - 3 /* Weird magic number (HIR-translation behaviour) */); - if cx.sess().source_map().lookup_char_pos(item.span.lo()).file.name_hash - == cx.sess().source_map().lookup_char_pos(test_mod_span.unwrap().lo()).file.name_hash; // Will never fail - if !matches!(item.kind, ItemKind::Mod(_)); - if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself - if !in_external_macro(cx.sess(), item.span); - if !is_from_proc_macro(cx, item); + let after: Vec<_> = items + .filter(|item| { + // Ignore the generated test main function + !(item.ident.name == sym::main + && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)) + }) + .collect(); - then { - span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined"); - }}; + if let Some(last) = after.last() + && after.iter().all(|&item| { + !matches!(item.kind, ItemKind::Mod(_)) + && !item.span.from_expansion() + && !is_from_proc_macro(cx, item) + }) + && !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id())) + { + let def_spans: Vec<_> = std::iter::once(test_mod.owner_id) + .chain(after.iter().map(|item| item.owner_id)) + .map(|id| cx.tcx.def_span(id)) + .collect(); - if let ItemKind::Mod(module) = item.kind && item.span.hi() == module.spans.inner_span.hi() { - // Check that it works the same way, the only I way I've found for #10713 - for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) { - if_chain! { - if attr.has_name(sym::cfg); - if let Some(mitems) = attr.meta_item_list(); - if let [mitem] = &*mitems; - if mitem.has_name(sym::test); - then { - was_test_mod_visited = true; - test_mod_span = Some(item.span); - } + span_lint_hir_and_then( + cx, + ITEMS_AFTER_TEST_MODULE, + test_mod.hir_id(), + def_spans, + "items after a test module", + |diag| { + if let Some(prev) = mod_pos.checked_sub(1) + && let prev = cx.tcx.hir().item(module.item_ids[prev]) + && let items_span = last.span.with_lo(test_mod.span.hi()) + && let Some(items) = snippet_opt(cx, items_span) + { + diag.multipart_suggestion_with_style( + "move the items to before the test module was defined", + vec![ + (prev.span.shrink_to_hi(), items), + (items_span, String::new()) + ], + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); } - } - } + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs new file mode 100644 index 0000000000000..43e1b92c9b9a7 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -0,0 +1,249 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::get_parent_as_impl; +use clippy_utils::source::snippet; +use clippy_utils::ty::{implements_trait, make_normalized_projection}; +use rustc_ast::Mutability; +use rustc_errors::Applicability; +use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for `iter` and `iter_mut` methods without an associated `IntoIterator for (&|&mut) Type` implementation. + /// + /// ### Why is this bad? + /// It's not bad, but having them is idiomatic and allows the type to be used in for loops directly + /// (`for val in &iter {}`), without having to first call `iter()` or `iter_mut()`. + /// + /// ### Example + /// ```rust + /// struct MySlice<'a>(&'a [u8]); + /// impl<'a> MySlice<'a> { + /// pub fn iter(&self) -> std::slice::Iter<'a, u8> { + /// self.0.iter() + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct MySlice<'a>(&'a [u8]); + /// impl<'a> MySlice<'a> { + /// pub fn iter(&self) -> std::slice::Iter<'a, u8> { + /// self.0.iter() + /// } + /// } + /// impl<'a> IntoIterator for &MySlice<'a> { + /// type Item = &'a u8; + /// type IntoIter = std::slice::Iter<'a, u8>; + /// fn into_iter(self) -> Self::IntoIter { + /// self.iter() + /// } + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub ITER_WITHOUT_INTO_ITER, + pedantic, + "implementing `iter(_mut)` without an associated `IntoIterator for (&|&mut) Type` impl" +} + +declare_clippy_lint! { + /// ### What it does + /// This is the opposite of the `iter_without_into_iter` lint. + /// It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method. + /// + /// ### Why is this bad? + /// It's not bad, but having them is idiomatic and allows the type to be used in iterator chains + /// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).iter()` syntax + /// in case of ambiguity with another `Intoiterator` impl. + /// + /// ### Example + /// ```rust + /// struct MySlice<'a>(&'a [u8]); + /// impl<'a> IntoIterator for &MySlice<'a> { + /// type Item = &'a u8; + /// type IntoIter = std::slice::Iter<'a, u8>; + /// fn into_iter(self) -> Self::IntoIter { + /// self.0.iter() + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct MySlice<'a>(&'a [u8]); + /// impl<'a> MySlice<'a> { + /// pub fn iter(&self) -> std::slice::Iter<'a, u8> { + /// self.into_iter() + /// } + /// } + /// impl<'a> IntoIterator for &MySlice<'a> { + /// type Item = &'a u8; + /// type IntoIter = std::slice::Iter<'a, u8>; + /// fn into_iter(self) -> Self::IntoIter { + /// self.0.iter() + /// } + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub INTO_ITER_WITHOUT_ITER, + pedantic, + "implementing `IntoIterator for (&|&mut) Type` without an inherent `iter(_mut)` method" +} + +declare_lint_pass!(IterWithoutIntoIter => [ITER_WITHOUT_INTO_ITER, INTO_ITER_WITHOUT_ITER]); + +/// Checks if a given type is nameable in a trait (impl). +/// RPIT is stable, but impl Trait in traits is not (yet), so when we have +/// a function such as `fn iter(&self) -> impl IntoIterator`, we can't +/// suggest `type IntoIter = impl IntoIterator`. +fn is_nameable_in_impl_trait(ty: &rustc_hir::Ty<'_>) -> bool { + !matches!(ty.kind, TyKind::OpaqueDef(..)) +} + +fn type_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool { + if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) { + cx.tcx.inherent_impls(ty_did).iter().any(|&did| { + cx.tcx + .associated_items(did) + .filter_by_name_unhygienic(method_name) + .next() + .is_some_and(|item| item.kind == ty::AssocKind::Fn) + }) + } else { + false + } +} + +impl LateLintPass<'_> for IterWithoutIntoIter { + fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { + if let ItemKind::Impl(imp) = item.kind + && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind + && let Some(trait_ref) = imp.of_trait + && trait_ref.trait_def_id().is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did)) + && let &ty::Ref(_, ty, mtbl) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() + && let expected_method_name = match mtbl { + Mutability::Mut => sym::iter_mut, + Mutability::Not => sym::iter, + } + && !type_has_inherent_method(cx, ty, expected_method_name) + && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| { + if item.ident.name == sym!(IntoIter) { + Some(cx.tcx.hir().impl_item(item.id).expect_type().span) + } else { + None + } + }) + { + span_lint_and_then( + cx, + INTO_ITER_WITHOUT_ITER, + item.span, + &format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"), + |diag| { + // The suggestion forwards to the `IntoIterator` impl and uses a form of UFCS + // to avoid name ambiguities, as there might be an inherent into_iter method + // that we don't want to call. + let sugg = format!( +" +impl {self_ty_without_ref} {{ + fn {expected_method_name}({ref_self}self) -> {iter_ty} {{ + <{ref_self}Self as IntoIterator>::into_iter(self) + }} +}} +", + self_ty_without_ref = snippet(cx, self_ty_without_ref.ty.span, ".."), + ref_self = mtbl.ref_prefix_str(), + iter_ty = snippet(cx, iter_assoc_span, ".."), + ); + + diag.span_suggestion_verbose( + item.span.shrink_to_lo(), + format!("consider implementing `{expected_method_name}`"), + sugg, + // Just like iter_without_into_iter, this suggestion is on a best effort basis + // and requires potentially adding lifetimes or moving them around. + Applicability::Unspecified + ); + } + ); + } + } + + fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) { + let item_did = item.owner_id.to_def_id(); + let (borrow_prefix, expected_implicit_self) = match item.ident.name { + sym::iter => ("&", ImplicitSelfKind::ImmRef), + sym::iter_mut => ("&mut ", ImplicitSelfKind::MutRef), + _ => return, + }; + + if let ImplItemKind::Fn(sig, _) = item.kind + && let FnRetTy::Return(ret) = sig.decl.output + && is_nameable_in_impl_trait(ret) + && cx.tcx.generics_of(item_did).params.is_empty() + && sig.decl.implicit_self == expected_implicit_self + && sig.decl.inputs.len() == 1 + && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()) + && imp.of_trait.is_none() + && let sig = cx.tcx.liberate_late_bound_regions( + item_did, + cx.tcx.fn_sig(item_did).instantiate_identity() + ) + && let ref_ty = sig.inputs()[0] + && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let Some(iterator_did) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let ret_ty = sig.output() + // Order is important here, we need to check that the `fn iter` return type actually implements `IntoIterator` + // *before* normalizing `<_ as IntoIterator>::Item` (otherwise make_normalized_projection ICEs) + && implements_trait(cx, ret_ty, iterator_did, &[]) + && let Some(iter_ty) = make_normalized_projection( + cx.tcx, + cx.param_env, + iterator_did, + sym!(Item), + [ret_ty], + ) + // Only lint if the `IntoIterator` impl doesn't actually exist + && !implements_trait(cx, ref_ty, into_iter_did, &[]) + { + let self_ty_snippet = format!("{borrow_prefix}{}", snippet(cx, imp.self_ty.span, "..")); + + span_lint_and_then( + cx, + ITER_WITHOUT_INTO_ITER, + item.span, + &format!("`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`", item.ident), + |diag| { + // Get the lower span of the `impl` block, and insert the suggestion right before it: + // impl X { + // ^ fn iter(&self) -> impl IntoIterator { ... } + // } + let span_behind_impl = cx.tcx + .def_span(cx.tcx.hir().parent_id(item.hir_id()).owner.def_id) + .shrink_to_lo(); + + let sugg = format!( +" +impl IntoIterator for {self_ty_snippet} {{ + type IntoIter = {ret_ty}; + type Iter = {iter_ty}; + fn into_iter() -> Self::IntoIter {{ + self.iter() + }} +}} +" + ); + diag.span_suggestion_verbose( + span_behind_impl, + format!("consider implementing `IntoIterator` for `{self_ty_snippet}`"), + sugg, + // Suggestion is on a best effort basis, might need some adjustments by the user + // such as adding some lifetimes in the associated types, or importing types. + Applicability::Unspecified, + ); + }); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 9b26c3573e18f..a4f3d49834531 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; @@ -50,12 +49,12 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { if !item.span.from_expansion(); - if let ItemKind::Const(hir_ty, generics, _) = &item.kind; + if let ItemKind::Const(_, generics, _) = &item.kind; // Since static items may not have generics, skip generic const items. // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it // doesn't account for empty where-clauses that only consist of keyword `where` IINM. if generics.params.is_empty() && !generics.has_where_clause_predicates; - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); if let ty::Array(element_type, cst) = ty.kind(); if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind(); if let Ok(element_count) = element_count.try_to_target_usize(cx.tcx); diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index d67d5899350a8..19f1e08b57ad1 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -17,26 +17,20 @@ declare_clippy_lint! { /// /// ### Example /// ```rust - /// async fn wait(f: impl std::future::Future) {} + /// async fn large_future(_x: [u8; 16 * 1024]) {} /// - /// async fn big_fut(arg: [u8; 1024]) {} - /// - /// pub async fn test() { - /// let fut = big_fut([0u8; 1024]); - /// wait(fut).await; + /// pub async fn trigger() { + /// large_future([0u8; 16 * 1024]).await; /// } /// ``` /// /// `Box::pin` the big future instead. /// /// ```rust - /// async fn wait(f: impl std::future::Future) {} - /// - /// async fn big_fut(arg: [u8; 1024]) {} + /// async fn large_future(_x: [u8; 16 * 1024]) {} /// - /// pub async fn test() { - /// let fut = Box::pin(big_fut([0u8; 1024])); - /// wait(fut).await; + /// pub async fn trigger() { + /// Box::pin(large_future([0u8; 16 * 1024])).await; /// } /// ``` #[clippy::version = "1.70.0"] diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index deba232bdd23e..c06b35ca0dabf 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -424,6 +424,14 @@ fn check_for_is_empty( item_name: Symbol, item_kind: &str, ) { + // Implementor may be a type alias, in which case we need to get the `DefId` of the aliased type to + // find the correct inherent impls. + let impl_ty = if let Some(adt) = cx.tcx.type_of(impl_ty).skip_binder().ty_adt_def() { + adt.did() + } else { + return; + }; + let is_empty = Symbol::intern("is_empty"); let is_empty = cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index f52614b62088f..0f35ec2766574 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -169,6 +169,7 @@ mod invalid_upcast_comparisons; mod items_after_statements; mod items_after_test_module; mod iter_not_returning_iterator; +mod iter_without_into_iter; mod large_const_arrays; mod large_enum_variant; mod large_futures; @@ -190,6 +191,7 @@ mod manual_async_fn; mod manual_bits; mod manual_clamp; mod manual_float_methods; +mod manual_hash_one; mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; @@ -230,6 +232,7 @@ mod mutex_atomic; mod needless_arbitrary_self_type; mod needless_bool; mod needless_borrowed_ref; +mod needless_borrows_for_generic_args; mod needless_continue; mod needless_else; mod needless_for_each; @@ -331,6 +334,7 @@ mod unit_return_expecting_ord; mod unit_types; mod unnamed_address; mod unnecessary_box_returns; +mod unnecessary_map_on_constructor; mod unnecessary_owned_empty_strings; mod unnecessary_self_imports; mod unnecessary_struct_initialization; @@ -610,7 +614,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: .collect(), )) }); - store.register_early_pass(|| Box::new(utils::format_args_collector::FormatArgsCollector)); + store.register_early_pass(|| Box::::default()); store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); store.register_late_pass(|_| Box::new(utils::author::Author)); let await_holding_invalid_types = conf.await_holding_invalid_types.clone(); @@ -637,7 +641,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool)); store.register_late_pass(|_| Box::new(needless_bool::BoolComparison)); store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach)); - store.register_late_pass(|_| Box::::default()); + store.register_late_pass(|_| Box::new(misc::LintPass)); store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction)); store.register_late_pass(|_| Box::new(mut_mut::MutMut)); store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed)); @@ -663,12 +667,19 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const; store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv()))); + let allowed_dotfiles = conf + .allowed_dotfiles + .iter() + .cloned() + .chain(methods::DEFAULT_ALLOWED_DOTFILES.iter().copied().map(ToOwned::to_owned)) + .collect::>(); store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, msrv(), allow_expect_in_tests, allow_unwrap_in_tests, + allowed_dotfiles.clone(), )) }); store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv()))); @@ -881,7 +892,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); - store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv()))); + store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); let future_size_threshold = conf.future_size_threshold; @@ -1104,6 +1115,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(implied_bounds_in_impls::ImpliedBoundsInImpls)); store.register_late_pass(|_| Box::new(missing_asserts_for_indexing::MissingAssertsForIndexing)); + store.register_late_pass(|_| Box::new(unnecessary_map_on_constructor::UnnecessaryMapOnConstructor)); + store.register_late_pass(move |_| { + Box::new(needless_borrows_for_generic_args::NeedlessBorrowsForGenericArgs::new( + msrv(), + )) + }); + store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); + store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs index 49425ff0a8e05..ac949b6726095 100644 --- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs +++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths}; use rustc_errors::Applicability; use rustc_hir::{Body, Closure, Expr, ExprKind}; @@ -62,7 +62,7 @@ impl LateLintPass<'_> for LinesFilterMapOk { if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind && is_trait_method(cx, expr, sym::Iterator) && (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") && - match_type(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), &paths::STD_IO_LINES) + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines) { let lint = match &fm_arg.kind { // Detect `Result::ok` diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 6edca2d55f649..0a2bd89eb3cd3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -5,7 +5,6 @@ use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor}; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, Pat, PatKind, Stmt}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; @@ -150,7 +149,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if l.pat.hir_id == self.var_id; if let PatKind::Binding(.., ident, _) = l.pat.kind; then { - let ty = l.ty.map(|ty| hir_ty_to_ty(self.cx.tcx, ty)); + let ty = l.ty.map(|_| self.cx.typeck_results().pat_ty(l.pat)); self.state = l.init.map_or(InitializeVisitorState::Declared(ident.name, ty), |init| { InitializeVisitorState::Initialized { diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 88db7ae6aece0..f09946955651b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// # let x = 1.0f32; /// if x.is_infinite() {} /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub MANUAL_IS_INFINITE, style, "use dedicated method to check if a float is infinite" @@ -51,7 +51,7 @@ declare_clippy_lint! { /// if x.is_finite() {} /// if x.is_finite() {} /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub MANUAL_IS_FINITE, style, "use dedicated method to check if a float is finite" @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { if !in_external_macro(cx.sess(), expr.span) && ( matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst) - || cx.tcx.features().active(sym!(const_float_classify)) + || cx.tcx.features().declared(sym!(const_float_classify)) ) && let ExprKind::Binary(kind, lhs, rhs) = expr.kind && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs new file mode 100644 index 0000000000000..ea91133545044 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -0,0 +1,133 @@ +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::source::snippet_opt; +use clippy_utils::visitors::{is_local_used, local_used_once}; +use clippy_utils::{is_trait_method, path_to_local_id}; +use rustc_errors::Applicability; +use rustc_hir::{BindingAnnotation, ExprKind, Local, Node, PatKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for cases where [`BuildHasher::hash_one`] can be used. + /// + /// [`BuildHasher::hash_one`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one + /// + /// ### Why is this bad? + /// It is more concise to use the `hash_one` method. + /// + /// ### Example + /// ```rust + /// use std::hash::{BuildHasher, Hash, Hasher}; + /// use std::collections::hash_map::RandomState; + /// + /// let s = RandomState::new(); + /// let value = vec![1, 2, 3]; + /// + /// let mut hasher = s.build_hasher(); + /// value.hash(&mut hasher); + /// let hash = hasher.finish(); + /// ``` + /// Use instead: + /// ```rust + /// use std::hash::BuildHasher; + /// use std::collections::hash_map::RandomState; + /// + /// let s = RandomState::new(); + /// let value = vec![1, 2, 3]; + /// + /// let hash = s.hash_one(&value); + /// ``` + #[clippy::version = "1.74.0"] + pub MANUAL_HASH_ONE, + complexity, + "manual implementations of `BuildHasher::hash_one`" +} + +pub struct ManualHashOne { + msrv: Msrv, +} + +impl ManualHashOne { + #[must_use] + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(ManualHashOne => [MANUAL_HASH_ONE]); + +impl LateLintPass<'_> for ManualHashOne { + fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + // `let mut hasher = seg.build_hasher();` + if let PatKind::Binding(BindingAnnotation::MUT, hasher, _, None) = local.pat.kind + && let Some(init) = local.init + && !init.span.from_expansion() + && let ExprKind::MethodCall(seg, build_hasher, [], _) = init.kind + && seg.ident.name == sym!(build_hasher) + + && let Node::Stmt(local_stmt) = cx.tcx.hir().get_parent(local.hir_id) + && let Node::Block(block) = cx.tcx.hir().get_parent(local_stmt.hir_id) + + && let mut stmts = block.stmts.iter() + .skip_while(|stmt| stmt.hir_id != local_stmt.hir_id) + .skip(1) + .filter(|&stmt| is_local_used(cx, stmt, hasher)) + + // `hashed_value.hash(&mut hasher);` + && let Some(hash_stmt) = stmts.next() + && let StmtKind::Semi(hash_expr) = hash_stmt.kind + && !hash_expr.span.from_expansion() + && let ExprKind::MethodCall(seg, hashed_value, [ref_to_hasher], _) = hash_expr.kind + && seg.ident.name == sym::hash + && is_trait_method(cx, hash_expr, sym::Hash) + && path_to_local_id(ref_to_hasher.peel_borrows(), hasher) + + && let maybe_finish_stmt = stmts.next() + // There should be no more statements referencing `hasher` + && stmts.next().is_none() + + // `hasher.finish()`, may be anywhere in a statement or the trailing expr of the block + && let Some(path_expr) = local_used_once(cx, (maybe_finish_stmt, block.expr), hasher) + && let Node::Expr(finish_expr) = cx.tcx.hir().get_parent(path_expr.hir_id) + && !finish_expr.span.from_expansion() + && let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind + && seg.ident.name == sym!(finish) + + && self.msrv.meets(msrvs::BUILD_HASHER_HASH_ONE) + { + span_lint_hir_and_then( + cx, + MANUAL_HASH_ONE, + finish_expr.hir_id, + finish_expr.span, + "manual implementation of `BuildHasher::hash_one`", + |diag| { + if let Some(build_hasher) = snippet_opt(cx, build_hasher.span) + && let Some(hashed_value) = snippet_opt(cx, hashed_value.span) + { + diag.multipart_suggestion( + "try", + vec![ + (local_stmt.span, String::new()), + (hash_stmt.span, String::new()), + ( + finish_expr.span, + // `needless_borrows_for_generic_args` will take care of + // removing the `&` when it isn't needed + format!("{build_hasher}.hash_one(&{hashed_value})") + ) + ], + Applicability::MachineApplicable, + ); + + } + }, + ); + } + } + + extract_msrv_attr!(LateContext); +} diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index c531137b785e8..2117308cd4009 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -136,9 +136,9 @@ fn emit_manual_let_else( // for this to be machine applicable. let mut app = Applicability::HasPlaceholders; let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app); - let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app); + let (sn_else, else_is_mac_call) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app); - let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) { + let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) && !else_is_mac_call { sn_else.into_owned() } else { format!("{{ {sn_else} }}") diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 0e22485db2c59..c12727c4a28cc 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -3,6 +3,7 @@ use clippy_utils::is_doc_hidden; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{self, VisibilityKind}; +use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -158,7 +159,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { let mut iter = def.variants.iter().filter_map(|v| { (matches!(v.data, hir::VariantData::Unit(_, _)) && v.ident.as_str().starts_with('_') - && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))) + && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)) + && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)) .then_some((v.def_id, v.span)) }); if let Some((id, span)) = iter.next() @@ -198,16 +200,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { enum_span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - if !cx.tcx.adt_def(enum_id).is_variant_list_non_exhaustive() - && let header_span = cx.sess().source_map().span_until_char(enum_span, '{') - && let Some(snippet) = snippet_opt(cx, header_span) - { - diag.span_suggestion( - header_span, - "add the attribute", - format!("#[non_exhaustive] {snippet}"), - Applicability::Unspecified, - ); + let header_span = cx.sess().source_map().span_until_char(enum_span, '{'); + if let Some(snippet) = snippet_opt(cx, header_span) { + diag.span_suggestion( + header_span, + "add the attribute", + format!("#[non_exhaustive] {snippet}"), + Applicability::Unspecified, + ); } diag.span_help(variant_span, "remove this variant"); }, diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index 1a69a48c582b0..f923413f4348b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -135,7 +135,7 @@ fn check_to_owned( if msrv.meets(msrvs::STRING_RETAIN) && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) - && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD) + && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id) && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 930386a60aa02..a23000e5fe15c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -961,7 +961,7 @@ declare_clippy_lint! { /// _ => todo!(), /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub REDUNDANT_GUARDS, complexity, "checks for unnecessary guards in match expressions" diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index c4f6852aedc3d..44dc29c36a6ba 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -8,8 +8,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath}; -use rustc_hir_analysis::hir_ty_to_ty; +use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, Guard, ItemKind, Node, Pat, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_span::sym; @@ -141,11 +140,15 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_> return same_type_and_consts(results.node_type(local.hir_id), results.expr_ty(expr)); }, // compare match_expr ty with RetTy in `fn foo() -> RetTy` - Node::Item(..) => { - if let Some(fn_decl) = p_node.fn_decl() { - if let FnRetTy::Return(ret_ty) = fn_decl.output { - return same_type_and_consts(hir_ty_to_ty(cx.tcx, ret_ty), cx.typeck_results().expr_ty(expr)); - } + Node::Item(item) => { + if let ItemKind::Fn(..) = item.kind { + let output = cx + .tcx + .fn_sig(item.owner_id) + .instantiate_identity() + .output() + .skip_binder(); + return same_type_and_consts(output, cx.typeck_results().expr_ty(expr)); } }, // check the parent expr for this whole block `{ match match_expr {..} }` diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 6e13148f2fc18..8f0083f812cc2 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt}; +use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt}; use clippy_utils::diagnostics::span_lint_and_note; use core::cmp::Ordering; use rustc_hir::{Arm, Expr, PatKind, RangeEnd}; @@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) Some(lhs) => constant(cx, cx.typeck_results(), lhs)?, None => { let min_val_const = ty.numeric_min_val(cx.tcx)?; - miri_to_const(cx, mir::ConstantKind::from_ty_const(min_val_const, cx.tcx))? + mir_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))? }, }; let rhs_const = match rhs { Some(rhs) => constant(cx, cx.typeck_results(), rhs)?, None => { let max_val_const = ty.numeric_max_val(cx.tcx)?; - miri_to_const(cx, mir::ConstantKind::from_ty_const(max_val_const, cx.tcx))? + mir_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))? }, }; let lhs_val = lhs_const.int_value(cx, ty)?; diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 29af4812351e3..0efeeacc9d97c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -2,11 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; use clippy_utils::source::snippet_with_applicability; use clippy_utils::visitors::{for_each_expr, is_local_used}; -use rustc_ast::LitKind; +use rustc_ast::{BorrowKind, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Guard, MatchSource, Node, Pat, PatKind}; use rustc_lint::LateContext; +use rustc_span::symbol::Ident; use rustc_span::Span; use std::ops::ControlFlow; @@ -34,32 +35,45 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { ], MatchSource::Normal, ) = if_expr.kind + && let Some(binding) = get_pat_binding(cx, scrutinee, outer_arm) { + let pat_span = match (arm.pat.kind, binding.byref_ident) { + (PatKind::Ref(pat, _), Some(_)) => pat.span, + (PatKind::Ref(..), None) | (_, Some(_)) => continue, + _ => arm.pat.span, + }; emit_redundant_guards( cx, outer_arm, if_expr.span, - scrutinee, - arm.pat.span, + pat_span, + &binding, arm.guard, ); } // `Some(x) if let Some(2) = x` - else if let Guard::IfLet(let_expr) = guard { + else if let Guard::IfLet(let_expr) = guard + && let Some(binding) = get_pat_binding(cx, let_expr.init, outer_arm) + { + let pat_span = match (let_expr.pat.kind, binding.byref_ident) { + (PatKind::Ref(pat, _), Some(_)) => pat.span, + (PatKind::Ref(..), None) | (_, Some(_)) => continue, + _ => let_expr.pat.span, + }; emit_redundant_guards( cx, outer_arm, let_expr.span, - let_expr.init, - let_expr.pat.span, + pat_span, + &binding, None, ); } // `Some(x) if x == Some(2)` + // `Some(x) if Some(2) == x` else if let Guard::If(if_expr) = guard && let ExprKind::Binary(bin_op, local, pat) = if_expr.kind && matches!(bin_op.node, BinOpKind::Eq) - && expr_can_be_pat(cx, pat) // Ensure they have the same type. If they don't, we'd need deref coercion which isn't // possible (currently) in a pattern. In some cases, you can use something like // `as_deref` or similar but in general, we shouldn't lint this as it'd create an @@ -67,43 +81,68 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { // // This isn't necessary in the other two checks, as they must be a pattern already. && cx.typeck_results().expr_ty(local) == cx.typeck_results().expr_ty(pat) + // Since we want to lint on both `x == Some(2)` and `Some(2) == x`, we might have to "swap" + // `local` and `pat`, depending on which side they are. + && let Some((binding, pat)) = get_pat_binding(cx, local, outer_arm) + .map(|binding| (binding, pat)) + .or_else(|| get_pat_binding(cx, pat, outer_arm).map(|binding| (binding, local))) + && expr_can_be_pat(cx, pat) { + let pat_span = match (pat.kind, binding.byref_ident) { + (ExprKind::AddrOf(BorrowKind::Ref, _, expr), Some(_)) => expr.span, + (ExprKind::AddrOf(..), None) | (_, Some(_)) => continue, + _ => pat.span, + }; emit_redundant_guards( cx, outer_arm, if_expr.span, - local, - pat.span, + pat_span, + &binding, None, ); } } } -fn get_pat_binding<'tcx>(cx: &LateContext<'tcx>, guard_expr: &Expr<'_>, outer_arm: &Arm<'tcx>) -> Option<(Span, bool)> { +struct PatBindingInfo { + span: Span, + byref_ident: Option, + is_field: bool, +} + +fn get_pat_binding<'tcx>( + cx: &LateContext<'tcx>, + guard_expr: &Expr<'_>, + outer_arm: &Arm<'tcx>, +) -> Option { if let Some(local) = path_to_local(guard_expr) && !is_local_used(cx, outer_arm.body, local) { let mut span = None; + let mut byref_ident = None; let mut multiple_bindings = false; // `each_binding` gives the `HirId` of the `Pat` itself, not the binding outer_arm.pat.walk(|pat| { - if let PatKind::Binding(_, hir_id, _, _) = pat.kind + if let PatKind::Binding(bind_annot, hir_id, ident, _) = pat.kind && hir_id == local - && span.replace(pat.span).is_some() { - multiple_bindings = true; - return false; + if matches!(bind_annot.0, rustc_ast::ByRef::Yes) { + let _ = byref_ident.insert(ident); + } + // the second call of `replace()` returns a `Some(span)`, meaning a multi-binding pattern + if span.replace(pat.span).is_some() { + multiple_bindings = true; + return false; + } } - true }); // Ignore bindings from or patterns, like `First(x) | Second(x, _) | Third(x, _, _)` if !multiple_bindings { - return span.map(|span| { - ( - span, - !matches!(cx.tcx.hir().get_parent(local), Node::PatField(_)), - ) + return span.map(|span| PatBindingInfo { + span, + byref_ident, + is_field: matches!(cx.tcx.hir().get_parent(local), Node::PatField(_)), }); } } @@ -115,14 +154,11 @@ fn emit_redundant_guards<'tcx>( cx: &LateContext<'tcx>, outer_arm: &Arm<'tcx>, guard_span: Span, - local: &Expr<'_>, pat_span: Span, + pat_binding: &PatBindingInfo, inner_guard: Option>, ) { let mut app = Applicability::MaybeIncorrect; - let Some((pat_binding, can_use_shorthand)) = get_pat_binding(cx, local, outer_arm) else { - return; - }; span_lint_and_then( cx, @@ -131,14 +167,21 @@ fn emit_redundant_guards<'tcx>( "redundant guard", |diag| { let binding_replacement = snippet_with_applicability(cx, pat_span, "", &mut app); + let suggestion_span = match *pat_binding { + PatBindingInfo { + span, + byref_ident: Some(ident), + is_field: true, + } => (span, format!("{ident}: {binding_replacement}")), + PatBindingInfo { + span, is_field: true, .. + } => (span.shrink_to_hi(), format!(": {binding_replacement}")), + PatBindingInfo { span, .. } => (span, binding_replacement.into_owned()), + }; diag.multipart_suggestion_verbose( "try", vec![ - if can_use_shorthand { - (pat_binding, binding_replacement.into_owned()) - } else { - (pat_binding.shrink_to_hi(), format!(": {binding_replacement}")) - }, + suggestion_span, ( guard_span.source_callsite().with_lo(outer_arm.pat.span.hi()), inner_guard.map_or_else(String::new, |guard| { diff --git a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs index f490a71755407..35370355f8340 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::is_local_used; -use clippy_utils::{path_to_local_id, paths, peel_blocks, peel_ref_operators, strip_pat_refs}; +use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind}; @@ -25,9 +25,9 @@ pub(super) fn check<'tcx>( if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind; if let ExprKind::Binary(ref op, l, r) = body.value.kind; if op.node == BinOpKind::Eq; - if match_type(cx, + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv).peel_refs(), - &paths::SLICE_ITER); + sym::SliceIter); let operand_is_arg = |expr| { let expr = peel_ref_operators(cx, peel_blocks(expr)); path_to_local_id(expr, arg_id) diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs index ddf3c9f27df29..926bd06bacbd2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -1,7 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::paths; use clippy_utils::source::snippet_with_context; -use clippy_utils::ty::{is_type_diagnostic_item, match_type}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -22,15 +20,14 @@ pub(super) fn check( } let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); - if let ty::Adt(_, subst) = obj_ty.kind() { - let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) { - "Rc" - } else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) { - "Arc" - } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { - "Weak" - } else { - return; + if let ty::Adt(adt, subst) = obj_ty.kind() + && let Some(name) = cx.tcx.get_diagnostic_name(adt.did()) + { + let caller_type = match name { + sym::Rc => "Rc", + sym::Arc => "Arc", + sym::RcWeak | sym::ArcWeak => "Weak", + _ => return, }; // Sometimes unnecessary ::<_> after Rc/Arc/Weak diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index d3e90e4bba392..40e487bf65058 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -131,13 +131,12 @@ pub(super) fn check<'tcx>( let mut applicability = Applicability::MachineApplicable; - //Special handling for `format!` as arg_root + // Special handling for `format!` as arg_root if let Some(macro_call) = root_macro_call_first_node(cx, arg_root) { - if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) { - return; - } - find_format_args(cx, arg_root, macro_call.expn, |format_args| { - let span = format_args_inputs_span(format_args); + if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) + && let Some(format_args) = find_format_args(cx, arg_root, macro_call.expn) + { + let span = format_args_inputs_span(&format_args); let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); span_lint_and_sugg( cx, @@ -148,7 +147,7 @@ pub(super) fn check<'tcx>( format!("unwrap_or_else({closure_args} panic!({sugg}))"), applicability, ); - }); + } return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index fafc970977009..33657254965c1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -8,6 +8,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::Binder; use rustc_span::{sym, Span}; @@ -36,6 +37,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & && let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id) && match_def_path(cx, def_id, &BOOL_THEN) && !is_from_proc_macro(cx, expr) + // Count the number of derefs needed to get to the bool because we need those in the suggestion + && let needed_derefs = cx.typeck_results().expr_adjustments(recv) + .iter() + .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) + .count() && let Some(param_snippet) = snippet_opt(cx, param.span) && let Some(filter) = snippet_opt(cx, recv.span) && let Some(map) = snippet_opt(cx, then_body.span) @@ -46,7 +52,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & call_span, "usage of `bool::then` in `filter_map`", "use `filter` then `map` instead", - format!("filter(|&{param_snippet}| {filter}).map(|{param_snippet}| {map})"), + format!( + "filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})", + derefs="*".repeat(needed_derefs) + ), Applicability::MachineApplicable, ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 66dfce3682b59..4040d3a5fe13b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; -use clippy_utils::{is_expr_path_def_path, paths, sugg}; +use clippy_utils::{is_path_diagnostic_item, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -13,7 +13,7 @@ use super::FROM_ITER_INSTEAD_OF_COLLECT; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) { if_chain! { - if is_expr_path_def_path(cx, func, &paths::FROM_ITERATOR_METHOD); + if is_path_diagnostic_item(cx, func, sym::from_iter_fn); let ty = cx.typeck_results().expr_ty(expr); let arg_ty = cx.typeck_results().expr_ty(&args[0]); if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index 631741d9290c8..6686d42c95f83 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth}; -use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -22,7 +21,7 @@ pub fn check( if_chain! { if args.is_empty() && method_name == sym::to_string; if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); + if cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did); if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id); let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver); let self_ty = args.type_at(0); diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs index 79c6d63254b28..99ea7f03df4e7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::higher::VecArgs; -use clippy_utils::{expr_or_init, is_trait_method, match_def_path, paths}; +use clippy_utils::{expr_or_init, is_trait_method}; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -26,14 +26,14 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) -> }; let did = adt.did(); - if match_def_path(cx, did, &paths::ARRAY_INTO_ITER) { + if cx.tcx.is_diagnostic_item(sym::ArrayIntoIter, did) { // For array::IntoIter, the length is the second generic // parameter. substs .const_at(1) .try_eval_target_usize(cx.tcx, cx.param_env) .map(u128::from) - } else if match_def_path(cx, did, &paths::SLICE_ITER) + } else if cx.tcx.is_diagnostic_item(sym::SliceIter, did) && let ExprKind::MethodCall(_, recv, ..) = iter.kind { if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() { @@ -47,9 +47,9 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) -> } else { None } - } else if match_def_path(cx, did, &paths::ITER_EMPTY) { + } else if cx.tcx.is_diagnostic_item(sym::IterEmpty, did) { Some(0) - } else if match_def_path(cx, did, &paths::ITER_ONCE) { + } else if cx.tcx.is_diagnostic_item(sym::IterOnce, did) { Some(1) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 81223fa8d954f..a935aea5075d7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -74,9 +74,11 @@ mod option_map_unwrap_or; mod or_fun_call; mod or_then_unwrap; mod path_buf_push_overwrite; +mod path_ends_with_ext; mod range_zip_with_len; mod read_line_without_trim; mod readonly_write_lock; +mod redundant_as_str; mod repeat_once; mod search_is_some; mod seek_from_current; @@ -120,9 +122,10 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty}; use if_chain::if_chain; +pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty}; @@ -2967,7 +2970,7 @@ declare_clippy_lint! { /// assert_eq!((*any_box).type_id(), TypeId::of::()); /// // ^ dereference first, to call `type_id` on `dyn Any` /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub TYPE_ID_ON_BOX, suspicious, "calling `.type_id()` on `Box`" @@ -3365,6 +3368,7 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// ### What it does /// Looks for calls to [`Stdin::read_line`] to read a line from the standard input /// into a string, then later attempting to parse this string into a type without first trimming it, which will /// always fail because the string has a trailing newline in it. @@ -3387,7 +3391,7 @@ declare_clippy_lint! { /// // ^^^^^^^^^^^ remove the trailing newline /// assert_eq!(num, 42); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub READ_LINE_WITHOUT_TRIM, correctness, "calling `Stdin::read_line`, then trying to parse it without first trimming" @@ -3415,7 +3419,7 @@ declare_clippy_lint! { /// # let c = 'c'; /// matches!(c, '\\' | '.' | '+' | '*' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub STRING_LIT_CHARS_ANY, restriction, "checks for `.chars().any(|i| i == c)`" @@ -3450,7 +3454,7 @@ declare_clippy_lint! { /// }) /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub FORMAT_COLLECT, perf, "`format!`ing every element in a collection, then collecting the strings into a new `String`" @@ -3471,7 +3475,7 @@ declare_clippy_lint! { /// let y = v.iter().collect::>(); /// assert_eq!(x, y); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub ITER_SKIP_ZERO, correctness, "disallows `.skip(0)`" @@ -3502,7 +3506,7 @@ declare_clippy_lint! { /// # let v = vec![]; /// _ = v.into_iter().filter(|i| i % 2 == 0).map(|i| really_expensive_fn(i)); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub FILTER_MAP_BOOL_THEN, style, "checks for usage of `bool::then` in `Iterator::filter_map`" @@ -3563,11 +3567,77 @@ declare_clippy_lint! { "calls to `.take()` or `.skip()` that are out of bounds" } +declare_clippy_lint! { + /// ### What it does + /// Looks for calls to `Path::ends_with` calls where the argument looks like a file extension. + /// + /// By default, Clippy has a short list of known filenames that start with a dot + /// but aren't necessarily file extensions (e.g. the `.git` folder), which are allowed by default. + /// The `allowed-dotfiles` configuration can be used to allow additional + /// file extensions that Clippy should not lint. + /// + /// ### Why is this bad? + /// This doesn't actually compare file extensions. Rather, `ends_with` compares the given argument + /// to the last **component** of the path and checks if it matches exactly. + /// + /// ### Known issues + /// File extensions are often at most three characters long, so this only lints in those cases + /// in an attempt to avoid false positives. + /// Any extension names longer than that are assumed to likely be real path components and are + /// therefore ignored. + /// + /// ### Example + /// ```rust + /// # use std::path::Path; + /// fn is_markdown(path: &Path) -> bool { + /// path.ends_with(".md") + /// } + /// ``` + /// Use instead: + /// ```rust + /// # use std::path::Path; + /// fn is_markdown(path: &Path) -> bool { + /// path.extension().is_some_and(|ext| ext == "md") + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub PATH_ENDS_WITH_EXT, + suspicious, + "attempting to compare file extensions using `Path::ends_with`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `as_str()` on a `String`` chained with a method available on the `String` itself. + /// + /// ### Why is this bad? + /// The `as_str()` conversion is pointless and can be removed for simplicity and cleanliness. + /// + /// ### Example + /// ```rust + /// # #![allow(unused)] + /// let owned_string = "This is a string".to_owned(); + /// owned_string.as_str().as_bytes(); + /// ``` + /// + /// Use instead: + /// ```rust + /// # #![allow(unused)] + /// let owned_string = "This is a string".to_owned(); + /// owned_string.as_bytes(); + /// ``` + #[clippy::version = "1.74.0"] + pub REDUNDANT_AS_STR, + complexity, + "`as_str` used to call a method on `str` that is also available on `String`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, + allowed_dotfiles: FxHashSet, } impl Methods { @@ -3577,12 +3647,14 @@ impl Methods { msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, + allowed_dotfiles: FxHashSet, ) -> Self { Self { avoid_breaking_exported_api, msrv, allow_expect_in_tests, allow_unwrap_in_tests, + allowed_dotfiles, } } } @@ -3703,6 +3775,8 @@ impl_lint_pass!(Methods => [ FILTER_MAP_BOOL_THEN, READONLY_WRITE_LOCK, ITER_OUT_OF_BOUNDS, + PATH_ENDS_WITH_EXT, + REDUNDANT_AS_STR, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3852,18 +3926,20 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if_chain! { if let TraitItemKind::Fn(ref sig, _) = item.kind; if sig.decl.implicit_self.has_implicit_self(); - if let Some(first_arg_ty) = sig.decl.inputs.iter().next(); - + if let Some(first_arg_hir_ty) = sig.decl.inputs.first(); + if let Some(&first_arg_ty) = cx.tcx.fn_sig(item.owner_id) + .instantiate_identity() + .inputs() + .skip_binder() + .first(); then { - let first_arg_span = first_arg_ty.span; - let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty(); wrong_self_convention::check( cx, item.ident.name.as_str(), self_ty, first_arg_ty, - first_arg_span, + first_arg_hir_ty.span, false, true, ); @@ -3929,6 +4005,7 @@ impl Methods { ("as_deref" | "as_deref_mut", []) => { needless_option_as_deref::check(cx, expr, recv, name); }, + ("as_bytes" | "is_empty", []) => if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) { redundant_as_str::check(cx, expr, recv, as_str_span, span); }, ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), @@ -3978,6 +4055,7 @@ impl Methods { if let ExprKind::MethodCall(.., span) = expr.kind { case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); } + path_ends_with_ext::check(cx, recv, arg, expr, &self.msrv, &self.allowed_dotfiles); }, ("expect", [_]) => { match method_call(recv) { diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs index 1c664e76d74f5..c0f5a27994515 100644 --- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs +++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs @@ -1,17 +1,17 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::paths; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::source_map::{Span, Spanned}; +use rustc_span::sym; use super::NONSENSICAL_OPEN_OPTIONS; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id) - && match_type(cx, cx.tcx.type_of(impl_id).instantiate_identity(), &paths::OPEN_OPTIONS) + && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions) { let mut options = Vec::new(); get_open_options(cx, recv, &mut options); @@ -40,7 +40,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); // Only proceed if this is a call on some object of type std::fs::OpenOptions - if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && !arguments.is_empty() { + if is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions) && !arguments.is_empty() { let argument_option = match arguments[0].kind { ExprKind::Lit(span) => { if let Spanned { diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 3e33f9193374e..d0c27f9631f7a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -32,8 +32,7 @@ pub(super) fn check( return; } - let deref_aliases: [&[&str]; 8] = [ - &paths::DEREF_MUT_TRAIT_METHOD, + let deref_aliases: [&[&str]; 7] = [ &paths::CSTRING_AS_C_STR, &paths::OS_STRING_AS_OS_STR, &paths::PATH_BUF_AS_PATH, @@ -49,6 +48,7 @@ pub(super) fn check( .opt_def_id() .map_or(false, |fun_def_id| { cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id) + || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id) || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path)) }) }, @@ -70,6 +70,7 @@ pub(super) fn check( then { let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap(); cx.tcx.is_diagnostic_item(sym::deref_method, method_did) + || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did) || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) } else { false diff --git a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs new file mode 100644 index 0000000000000..3347c8c162015 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs @@ -0,0 +1,53 @@ +use super::PATH_ENDS_WITH_EXT; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs; +use clippy_utils::msrvs::Msrv; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_ast::{LitKind, StrStyle}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::sym; +use std::fmt::Write; + +pub const DEFAULT_ALLOWED_DOTFILES: &[&str] = &[ + "git", "svn", "gem", "npm", "vim", "env", "rnd", "ssh", "vnc", "smb", "nvm", "bin", +]; + +pub(super) fn check( + cx: &LateContext<'_>, + recv: &Expr<'_>, + path: &Expr<'_>, + expr: &Expr<'_>, + msrv: &Msrv, + allowed_dotfiles: &FxHashSet, +) { + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::Path) + && !path.span.from_expansion() + && let ExprKind::Lit(lit) = path.kind + && let LitKind::Str(path, StrStyle::Cooked) = lit.node + && let Some(path) = path.as_str().strip_prefix('.') + && (1..=3).contains(&path.len()) + && !allowed_dotfiles.contains(path) + && path.chars().all(char::is_alphanumeric) + { + let mut sugg = snippet(cx, recv.span, "..").into_owned(); + if msrv.meets(msrvs::OPTION_IS_SOME_AND) { + let _ = write!(sugg, r#".extension().is_some_and(|ext| ext == "{path}")"#); + } else { + let _ = write!(sugg, r#".extension().map_or(false, |ext| ext == "{path}")"#); + }; + + span_lint_and_sugg( + cx, + PATH_ENDS_WITH_EXT, + expr.span, + "this looks like a failed attempt at checking for the file extension", + "try", + sugg, + Applicability::MaybeIncorrect + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs new file mode 100644 index 0000000000000..98cd6afc2b79f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs @@ -0,0 +1,34 @@ +use super::REDUNDANT_AS_STR; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::query::Key; +use rustc_span::Span; + +pub(super) fn check( + cx: &LateContext<'_>, + _expr: &Expr<'_>, + recv: &Expr<'_>, + as_str_span: Span, + other_method_span: Span, +) { + if cx + .tcx + .lang_items() + .string() + .is_some_and(|id| Some(id) == cx.typeck_results().expr_ty(recv).ty_adt_id()) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + REDUNDANT_AS_STR, + as_str_span.to(other_method_span), + "this `as_str` is redundant and can be removed as the method immediately following exists on `String` too", + "try", + snippet_with_applicability(cx, other_method_span, "..", &mut applicability).into_owned(), + applicability, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs index f3d6a15ede01b..4ea87027a9e6f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs @@ -2,18 +2,19 @@ use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_span::sym; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_trait_def_id, match_def_path, paths}; +use clippy_utils::{match_def_path, paths}; use super::SEEK_FROM_CURRENT; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { let ty = cx.typeck_results().expr_ty(recv); - if let Some(def_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) { + if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) { if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) { let mut applicability = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs index 787e9e0ebd245..50d4de7a68007 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths}; +use clippy_utils::{is_expr_used_or_unified, match_def_path, paths}; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_span::Span; +use rustc_span::{sym, Span}; use super::SEEK_TO_START_INSTEAD_OF_REWIND; @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>( return; } - if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) && + if let Some(seek_trait_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) && implements_trait(cx, ty, seek_trait_id, &[]) && let ExprKind::Call(func, args1) = arg.kind && let ExprKind::Path(ref path) = func.kind && diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs index bc8f017676415..8959e2c1d75f7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::paths; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::{Applicability, Diagnostic}; use rustc_lint::LateContext; -use rustc_span::Span; +use rustc_span::{sym, Span}; use {rustc_ast as ast, rustc_hir as hir}; use super::SUSPICIOUS_COMMAND_ARG_SPACE; @@ -11,7 +10,7 @@ use super::SUSPICIOUS_COMMAND_ARG_SPACE; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if match_type(cx, ty, &paths::STD_PROCESS_COMMAND) + if is_type_diagnostic_item(cx, ty, sym::Command) && let hir::ExprKind::Lit(lit) = &arg.kind && let ast::LitKind::Str(s, _) = &lit.node && let Some((arg1, arg2)) = s.as_str().split_once(' ') diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 937aac8d25ef0..3e19d72ec912a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -24,7 +24,6 @@ fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) - } } -#[expect(clippy::too_many_lines)] pub(super) fn check( cx: &LateContext<'_>, expr: &hir::Expr<'_>, @@ -101,15 +100,11 @@ pub(super) fn check( (expr.span.with_lo(args[0].span.hi()), String::new()), ]), ("None", "unwrap_or_else", _) => match args[0].kind { - hir::ExprKind::Closure(hir::Closure { - fn_decl: - hir::FnDecl { - output: hir::FnRetTy::DefaultReturn(span) | hir::FnRetTy::Return(hir::Ty { span, .. }), - .. - }, - .. - }) => Some(vec![ - (expr.span.with_hi(span.hi()), String::new()), + hir::ExprKind::Closure(hir::Closure { body, .. }) => Some(vec![ + ( + expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()), + String::new(), + ), (expr.span.with_lo(args[0].span.hi()), String::new()), ]), _ => None, 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 5c5ee26205287..50d6f3b7e55f5 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 @@ -401,7 +401,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< = get_callee_generic_args_and_args(cx, parent_expr) { // FIXME: the `instantiate_identity()` below seems incorrect, since we eventually - // call `tcx.try_subst_and_normalize_erasing_regions` further down + // call `tcx.try_instantiate_and_normalize_erasing_regions` further down // (i.e., we are explicitly not in the identity context). let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder(); if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id) @@ -452,7 +452,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let output_ty = fn_sig.output(); if output_ty.contains(*param_ty) { - if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions( + if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, cx.param_env, EarlyBinder::bind(output_ty)) { expr = parent_expr; ty = new_ty; diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 303f012569087..9c8b47fb30327 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -1,24 +1,22 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_hir_and_then}; -use clippy_utils::source::{snippet, snippet_opt, snippet_with_context}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::source::{snippet, snippet_with_context}; +use clippy_utils::sugg::Sugg; +use clippy_utils::{ + any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats, + last_path_segment, SpanlessEq, +}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, Stmt, - StmtKind, TyKind, + BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, }; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; -use rustc_span::hygiene::DesugaringKind; -use rustc_span::source_map::{ExpnKind, Span}; - -use clippy_utils::sugg::Sugg; -use clippy_utils::{ - get_parent_expr, in_constant, is_integer_literal, is_lint_allowed, is_no_std_crate, iter_input_pats, - last_path_segment, SpanlessEq, -}; +use rustc_span::source_map::Span; use crate::ref_patterns::REF_PATTERNS; @@ -56,6 +54,7 @@ declare_clippy_lint! { style, "an entire binding declared as `ref`, in a function argument or a `let` statement" } + declare_clippy_lint! { /// ### What it does /// Checks for the use of bindings with a single leading @@ -103,51 +102,13 @@ declare_clippy_lint! { "using a short circuit boolean condition as a statement" } -declare_clippy_lint! { - /// ### What it does - /// Catch casts from `0` to some pointer type - /// - /// ### Why is this bad? - /// This generally means `null` and is better expressed as - /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}. - /// - /// ### Example - /// ```rust - /// let a = 0 as *const u32; - /// ``` - /// - /// Use instead: - /// ```rust - /// let a = std::ptr::null::(); - /// ``` - #[clippy::version = "pre 1.29.0"] - pub ZERO_PTR, - style, - "using `0 as *{const, mut} T`" -} - -pub struct LintPass { - std_or_core: &'static str, -} -impl Default for LintPass { - fn default() -> Self { - Self { std_or_core: "std" } - } -} -impl_lint_pass!(LintPass => [ +declare_lint_pass!(LintPass => [ TOPLEVEL_REF_ARG, USED_UNDERSCORE_BINDING, SHORT_CIRCUIT_STATEMENT, - ZERO_PTR, ]); impl<'tcx> LateLintPass<'tcx> for LintPass { - fn check_crate(&mut self, cx: &LateContext<'_>) { - if is_no_std_crate(cx) { - self.std_or_core = "core"; - } - } - fn check_fn( &mut self, cx: &LateContext<'tcx>, @@ -253,50 +214,56 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Cast(e, ty) = expr.kind { - self.check_cast(cx, expr.span, e, ty); - return; - } - if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) { - // Don't lint things expanded by #[derive(...)], etc or `await` desugaring + if in_external_macro(cx.sess(), expr.span) + || expr.span.desugaring_kind().is_some() + || any_parent_is_automatically_derived(cx.tcx, expr.hir_id) + { return; } - let sym; - let binding = match expr.kind { - ExprKind::Path(ref qpath) if !matches!(qpath, hir::QPath::LangItem(..)) => { - let binding = last_path_segment(qpath).ident.as_str(); - if binding.starts_with('_') && - !binding.starts_with("__") && - binding != "_result" && // FIXME: #944 - is_used(cx, expr) && - // don't lint if the declaration is in a macro - non_macro_local(cx, cx.qpath_res(qpath, expr.hir_id)) + let (definition_hir_id, ident) = match expr.kind { + ExprKind::Path(ref qpath) => { + if let QPath::Resolved(None, path) = qpath + && let Res::Local(id) = path.res + && is_used(cx, expr) { - Some(binding) + (id, last_path_segment(qpath).ident) } else { - None + return; } }, - ExprKind::Field(_, ident) => { - sym = ident.name; - let name = sym.as_str(); - if name.starts_with('_') && !name.starts_with("__") { - Some(name) + ExprKind::Field(recv, ident) => { + if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def() + && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name) + && let Some(local_did) = field.did.as_local() + && let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(local_did) + && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data() + { + (hir_id, ident) } else { - None + return; } }, - _ => None, + _ => return, }; - if let Some(binding) = binding { - span_lint( + + let name = ident.name.as_str(); + if name.starts_with('_') + && !name.starts_with("__") + && let definition_span = cx.tcx.hir().span(definition_hir_id) + && !definition_span.from_expansion() + && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id]) + { + span_lint_and_then( cx, USED_UNDERSCORE_BINDING, expr.span, &format!( - "used binding `{binding}` which is prefixed with an underscore. A leading \ + "used binding `{name}` which is prefixed with an underscore. A leading \ underscore signals that a binding will not be used" ), + |diag| { + diag.span_note(definition_span, format!("`{name}` is defined here")); + } ); } } @@ -311,50 +278,3 @@ fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => is_used(cx, parent), }) } - -/// Tests whether an expression is in a macro expansion (e.g., something -/// generated by `#[derive(...)]` or the like). -fn in_attributes_expansion(expr: &Expr<'_>) -> bool { - use rustc_span::hygiene::MacroKind; - if expr.span.from_expansion() { - let data = expr.span.ctxt().outer_expn_data(); - matches!(data.kind, ExpnKind::Macro(MacroKind::Attr | MacroKind::Derive, _)) - } else { - false - } -} - -/// Tests whether `res` is a variable defined outside a macro. -fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool { - if let def::Res::Local(id) = res { - !cx.tcx.hir().span(id).from_expansion() - } else { - false - } -} - -impl LintPass { - fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) { - if_chain! { - if let TyKind::Ptr(ref mut_ty) = ty.kind; - if is_integer_literal(e, 0); - if !in_constant(cx, e.hir_id); - then { - let (msg, sugg_fn) = match mut_ty.mutbl { - Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"), - Mutability::Not => ("`0 as *const _` detected", "ptr::null"), - }; - - let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind { - (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MachineApplicable) - } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) { - (format!("{}::{sugg_fn}::<{mut_ty_snip}>()", self.std_or_core), Applicability::MachineApplicable) - } else { - // `MaybeIncorrect` as type inference may not work with the suggested code - (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MaybeIncorrect) - }; - span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs index c17f00c427515..136947a2c8cd3 100644 --- a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs +++ b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs @@ -15,6 +15,10 @@ declare_clippy_lint! { /// A good custom message should be more about why the failure of the assertion is problematic /// and not what is failed because the assertion already conveys that. /// + /// Although the same reasoning applies to testing functions, this lint ignores them as they would be too noisy. + /// Also, in most cases understanding the test failure would be easier + /// compared to understanding a complex invariant distributed around the codebase. + /// /// ### Known problems /// This lint cannot check the quality of the custom panic messages. /// Hence, you can suppress this lint simply by adding placeholder messages diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 3b7eccad79df8..f598a65d2e488 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -7,7 +7,6 @@ use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Constness, FnDecl, GenericParamKind}; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -124,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { FnKind::Method(_, sig, ..) => { if trait_ref_of_method(cx, def_id).is_some() || already_const(sig.header) - || method_accepts_droppable(cx, sig.decl.inputs) + || method_accepts_droppable(cx, def_id) { return; } @@ -165,12 +164,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { /// Returns true if any of the method parameters is a type that implements `Drop`. The method /// can't be made const then, because `drop` can't be const-evaluated. -fn method_accepts_droppable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { +fn method_accepts_droppable(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { + let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); + // If any of the params are droppable, return true - param_tys.iter().any(|hir_ty| { - let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty); - has_drop(cx, ty_ty) - }) + sig.inputs().iter().any(|&ty| has_drop(cx, ty)) } // We don't have to lint on something that's already `const` diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 2f63b9b9f0b8e..f0b865be8042d 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -1,9 +1,9 @@ use std::ops::ControlFlow; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{for_each_expr, Visitable}; -use clippy_utils::{is_path_lang_item, paths}; +use clippy_utils::is_path_lang_item; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; @@ -114,9 +114,11 @@ fn should_lint<'tcx>( if let ExprKind::MethodCall(path, recv, ..) = &expr.kind { let recv_ty = typeck_results.expr_ty(recv).peel_refs(); - if path.ident.name == sym::debug_struct && match_type(cx, recv_ty, &paths::FORMATTER) { + if path.ident.name == sym::debug_struct && is_type_diagnostic_item(cx, recv_ty, sym::Formatter) { has_debug_struct = true; - } else if path.ident.name == sym!(finish_non_exhaustive) && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) { + } else if path.ident.name == sym!(finish_non_exhaustive) + && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct) + { has_finish_non_exhaustive = true; } } @@ -137,7 +139,7 @@ fn as_field_call<'tcx>( ) -> Option { if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind && let recv_ty = typeck_results.expr_ty(recv).peel_refs() - && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) + && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct) && path.ident.name == sym::field && let ExprKind::Lit(lit) = &debug_field.kind && let LitKind::Str(sym, ..) = lit.node diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 367cd6bd41337..e87aea263d48e 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -134,15 +134,27 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { } } +fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool { + !matches!(stmt.kind, StmtKind::Item(..)) +} + impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { // fix #10776 ExprKind::Block(block, ..) => match (block.stmts, block.expr) { - ([], Some(e)) => self.visit_expr(e), - ([stmt], None) => match stmt.kind { - StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), - _ => {}, + (stmts, Some(e)) => { + if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) { + self.visit_expr(e); + } + }, + ([first @ .., stmt], None) => { + if first.iter().all(|stmt| !stmt_might_diverge(stmt)) { + match stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), + _ => {}, + } + } }, _ => {}, }, diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs new file mode 100644 index 0000000000000..d55c77a92b158 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -0,0 +1,410 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap}; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::source::snippet_with_context; +use clippy_utils::ty::is_copy; +use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode}; +use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{Body, Expr, ExprKind, Mutability, Path, QPath}; +use rustc_index::bit_set::BitSet; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::mir::{Rvalue, StatementKind}; +use rustc_middle::ty::{ + self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, List, ParamTy, ProjectionPredicate, Ty, +}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::symbol::sym; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{Obligation, ObligationCause}; +use std::collections::VecDeque; + +declare_clippy_lint! { + /// ### What it does + /// Checks for borrow operations (`&`) that used as a generic argument to a + /// function when the borrowed value could be used. + /// + /// ### Why is this bad? + /// Suggests that the receiver of the expression borrows + /// the expression. + /// + /// ### Known problems + /// The lint cannot tell when the implementation of a trait + /// for `&T` and `T` do different things. Removing a borrow + /// in such a case can change the semantics of the code. + /// + /// ### Example + /// ```rust + /// fn f(_: impl AsRef) {} + /// + /// let x = "foo"; + /// f(&x); + /// ``` + /// + /// Use instead: + /// ```rust + /// fn f(_: impl AsRef) {} + /// + /// let x = "foo"; + /// f(x); + /// ``` + #[clippy::version = "pre 1.29.0"] + pub NEEDLESS_BORROWS_FOR_GENERIC_ARGS, + style, + "taking a reference that is going to be automatically dereferenced" +} + +pub struct NeedlessBorrowsForGenericArgs<'tcx> { + /// Stack of (body owner, `PossibleBorrowerMap`) pairs. Used by + /// `needless_borrow_impl_arg_position` to determine when a borrowed expression can instead + /// be moved. + possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, + + // `IntoIterator` for arrays requires Rust 1.53. + msrv: Msrv, +} +impl_lint_pass!(NeedlessBorrowsForGenericArgs<'_> => [NEEDLESS_BORROWS_FOR_GENERIC_ARGS]); + +impl NeedlessBorrowsForGenericArgs<'_> { + #[must_use] + pub fn new(msrv: Msrv) -> Self { + Self { + possible_borrowers: Vec::new(), + msrv, + } + } +} + +impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if matches!(expr.kind, ExprKind::AddrOf(..)) + && !expr.span.from_expansion() + && let Some(use_cx) = expr_use_ctxt(cx, expr) + && !use_cx.is_ty_unified + && let Some(DefinedTy::Mir(ty)) = use_cx.node.defined_ty(cx) + && let ty::Param(ty) = *ty.value.skip_binder().kind() + && let Some((hir_id, fn_id, i)) = match use_cx.node { + ExprUseNode::MethodArg(_, _, 0) => None, + ExprUseNode::MethodArg(hir_id, None, i) => { + cx.typeck_results().type_dependent_def_id(hir_id).map(|id| (hir_id, id, i)) + }, + ExprUseNode::FnArg(&Expr { kind: ExprKind::Path(ref p), hir_id, .. }, i) + if !path_has_args(p) => match cx.typeck_results().qpath_res(p, hir_id) { + Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) => { + Some((hir_id, id, i)) + }, + _ => None, + }, + _ => None, + } && let count = needless_borrow_count( + cx, + &mut self.possible_borrowers, + fn_id, + cx.typeck_results().node_args(hir_id), + i, + ty, + expr, + &self.msrv, + ) && count != 0 + { + span_lint_and_then( + cx, + NEEDLESS_BORROWS_FOR_GENERIC_ARGS, + expr.span, + "the borrowed expression implements the required traits", + |diag| { + let mut app = Applicability::MachineApplicable; + let snip_span = peel_n_hir_expr_refs(expr, count).0.span; + let snip = snippet_with_context(cx, snip_span, expr.span.ctxt(), "..", &mut app).0; + diag.span_suggestion(expr.span, "change this to", snip.into_owned(), app); + } + ); + } + } + + fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| { + local_def_id == cx.tcx.hir().body_owner_def_id(body.id()) + }) { + self.possible_borrowers.pop(); + } + } + + extract_msrv_attr!(LateContext); +} + +fn path_has_args(p: &QPath<'_>) -> bool { + match *p { + QPath::Resolved(_, Path { segments: [.., s], .. }) | QPath::TypeRelative(_, s) => s.args.is_some(), + _ => false, + } +} + +/// Checks for the number of borrow expressions which can be removed from the given expression +/// where the expression is used as an argument to a function expecting a generic type. +/// +/// The following constraints will be checked: +/// * The borrowed expression meets all the generic type's constraints. +/// * The generic type appears only once in the functions signature. +/// * The borrowed value will not be moved if it is used later in the function. +#[expect(clippy::too_many_arguments)] +fn needless_borrow_count<'tcx>( + cx: &LateContext<'tcx>, + possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, + fn_id: DefId, + callee_args: &'tcx List>, + arg_index: usize, + param_ty: ParamTy, + mut expr: &Expr<'tcx>, + msrv: &Msrv, +) -> usize { + let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait(); + let sized_trait_def_id = cx.tcx.lang_items().sized_trait(); + + let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder(); + let predicates = cx.tcx.param_env(fn_id).caller_bounds(); + let projection_predicates = predicates + .iter() + .filter_map(|predicate| { + if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() { + Some(projection_predicate) + } else { + None + } + }) + .collect::>(); + + let mut trait_with_ref_mut_self_method = false; + + // If no traits were found, or only the `Destruct`, `Sized`, or `Any` traits were found, return. + if predicates + .iter() + .filter_map(|predicate| { + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() + && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) + { + Some(trait_predicate.trait_ref.def_id) + } else { + None + } + }) + .inspect(|trait_def_id| { + trait_with_ref_mut_self_method |= has_ref_mut_self_method(cx, *trait_def_id); + }) + .all(|trait_def_id| { + Some(trait_def_id) == destruct_trait_def_id + || Some(trait_def_id) == sized_trait_def_id + || cx.tcx.is_diagnostic_item(sym::Any, trait_def_id) + }) + { + return 0; + } + + // See: + // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1289294201 + // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1292225232 + if projection_predicates + .iter() + .any(|projection_predicate| is_mixed_projection_predicate(cx, fn_id, projection_predicate)) + { + return 0; + } + + // `args_with_referent_ty` can be constructed outside of `check_referent` because the same + // elements are modified each time `check_referent` is called. + let mut args_with_referent_ty = callee_args.to_vec(); + + let mut check_reference_and_referent = |reference, referent| { + let referent_ty = cx.typeck_results().expr_ty(referent); + + if !is_copy(cx, referent_ty) + && (referent_ty.has_significant_drop(cx.tcx, cx.param_env) + || !referent_used_exactly_once(cx, possible_borrowers, reference)) + { + return false; + } + + // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 + if trait_with_ref_mut_self_method && !matches!(referent_ty.kind(), ty::Ref(_, _, Mutability::Mut)) { + return false; + } + + if !replace_types( + cx, + param_ty, + referent_ty, + fn_sig, + arg_index, + &projection_predicates, + &mut args_with_referent_ty, + ) { + return false; + } + + predicates.iter().all(|predicate| { + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() + && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) + && let ty::Param(param_ty) = trait_predicate.self_ty().kind() + && let GenericArgKind::Type(ty) = args_with_referent_ty[param_ty.index as usize].unpack() + && ty.is_array() + && !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) + { + return false; + } + + let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); + let infcx = cx.tcx.infer_ctxt().build(); + infcx.predicate_must_hold_modulo_regions(&obligation) + }) + }; + + let mut count = 0; + while let ExprKind::AddrOf(_, _, referent) = expr.kind { + if !check_reference_and_referent(expr, referent) { + break; + } + expr = referent; + count += 1; + } + count +} + +fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool { + cx.tcx + .associated_items(trait_def_id) + .in_definition_order() + .any(|assoc_item| { + if assoc_item.fn_has_self_parameter { + let self_ty = cx + .tcx + .fn_sig(assoc_item.def_id) + .instantiate_identity() + .skip_binder() + .inputs()[0]; + matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Mut)) + } else { + false + } + }) +} + +fn is_mixed_projection_predicate<'tcx>( + cx: &LateContext<'tcx>, + callee_def_id: DefId, + projection_predicate: &ProjectionPredicate<'tcx>, +) -> bool { + let generics = cx.tcx.generics_of(callee_def_id); + // The predicate requires the projected type to equal a type parameter from the parent context. + if let Some(term_ty) = projection_predicate.term.ty() + && let ty::Param(term_param_ty) = term_ty.kind() + && (term_param_ty.index as usize) < generics.parent_count + { + // The inner-most self type is a type parameter from the current function. + let mut projection_ty = projection_predicate.projection_ty; + loop { + match projection_ty.self_ty().kind() { + ty::Alias(ty::Projection, inner_projection_ty) => { + projection_ty = *inner_projection_ty; + } + ty::Param(param_ty) => { + return (param_ty.index as usize) >= generics.parent_count; + } + _ => { + return false; + } + } + } + } else { + false + } +} + +fn referent_used_exactly_once<'tcx>( + cx: &LateContext<'tcx>, + possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, + reference: &Expr<'tcx>, +) -> bool { + if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id) + && let Some(local) = expr_local(cx.tcx, reference) + && let [location] = *local_assignments(mir, local).as_slice() + && let block_data = &mir.basic_blocks[location.block] + && let Some(statement) = block_data.statements.get(location.statement_index) + && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind + && !place.is_indirect_first_projection() + { + let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); + if possible_borrowers + .last() + .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id) + { + possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); + } + let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1; + // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is + // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of + // itself. See the comment in that method for an explanation as to why. + possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location) + && used_exactly_once(mir, place.local).unwrap_or(false) + } else { + false + } +} + +// Iteratively replaces `param_ty` with `new_ty` in `args`, and similarly for each resulting +// projected type that is a type parameter. Returns `false` if replacing the types would have an +// effect on the function signature beyond substituting `new_ty` for `param_ty`. +// See: https://github.com/rust-lang/rust-clippy/pull/9136#discussion_r927212757 +fn replace_types<'tcx>( + cx: &LateContext<'tcx>, + param_ty: ParamTy, + new_ty: Ty<'tcx>, + fn_sig: FnSig<'tcx>, + arg_index: usize, + projection_predicates: &[ProjectionPredicate<'tcx>], + args: &mut [ty::GenericArg<'tcx>], +) -> bool { + let mut replaced = BitSet::new_empty(args.len()); + + let mut deque = VecDeque::with_capacity(args.len()); + deque.push_back((param_ty, new_ty)); + + while let Some((param_ty, new_ty)) = deque.pop_front() { + // If `replaced.is_empty()`, then `param_ty` and `new_ty` are those initially passed in. + if !fn_sig + .inputs_and_output + .iter() + .enumerate() + .all(|(i, ty)| (replaced.is_empty() && i == arg_index) || !ty.contains(param_ty.to_ty(cx.tcx))) + { + return false; + } + + args[param_ty.index as usize] = ty::GenericArg::from(new_ty); + + // The `replaced.insert(...)` check provides some protection against infinite loops. + if replaced.insert(param_ty.index) { + for projection_predicate in projection_predicates { + if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx) + && let Some(term_ty) = projection_predicate.term.ty() + && let ty::Param(term_param_ty) = term_ty.kind() + { + let projection = cx.tcx.mk_ty_from_kind(ty::Alias( + ty::Projection, + projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty), + )); + + if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) + && args[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty) + { + deque.push_back((*term_param_ty, projected_ty)); + } + } + } + } + } + + true +} diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index 7b00eabf97b41..212d6234bdb3c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -1,6 +1,7 @@ use super::needless_pass_by_value::requires_exact_signature; use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; +use clippy_utils::visitors::for_each_expr_with_closures; use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::Applicability; @@ -9,7 +10,7 @@ use rustc_hir::{ Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath, }; use rustc_hir_typeck::expr_use_visitor as euv; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::associated_body; use rustc_middle::hir::nested_filter::OnlyBodies; @@ -21,6 +22,8 @@ use rustc_span::symbol::kw; use rustc_span::Span; use rustc_target::spec::abi::Abi; +use core::ops::ControlFlow; + declare_clippy_lint! { /// ### What it does /// Check if a `&mut` function argument is actually used mutably. @@ -44,9 +47,9 @@ declare_clippy_lint! { /// 12 + *y /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub NEEDLESS_PASS_BY_REF_MUT, - suspicious, + nursery, "using a `&mut` argument when it's not mutated" } @@ -95,6 +98,30 @@ fn should_skip<'tcx>( is_from_proc_macro(cx, &input) } +fn check_closures<'tcx>( + ctx: &mut MutablyUsedVariablesCtxt<'tcx>, + cx: &LateContext<'tcx>, + infcx: &InferCtxt<'tcx>, + checked_closures: &mut FxHashSet, + closures: FxHashSet, +) { + let hir = cx.tcx.hir(); + for closure in closures { + if !checked_closures.insert(closure) { + continue; + } + ctx.prev_bind = None; + ctx.prev_move_to_closure.clear(); + if let Some(body) = hir + .find_by_def_id(closure) + .and_then(associated_body) + .map(|(_, body_id)| hir.body(body_id)) + { + euv::ExprUseVisitor::new(ctx, infcx, closure, cx.param_env, cx.typeck_results()).consume_body(body); + } + } +} + impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { fn check_fn( &mut self, @@ -161,25 +188,22 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body); if is_async { let mut checked_closures = FxHashSet::default(); + + // We retrieve all the closures declared in the async function because they will + // not be found by `euv::Delegate`. + let mut closures: FxHashSet = FxHashSet::default(); + for_each_expr_with_closures(cx, body, |expr| { + if let ExprKind::Closure(closure) = expr.kind { + closures.insert(closure.def_id); + } + ControlFlow::<()>::Continue(()) + }); + check_closures(&mut ctx, cx, &infcx, &mut checked_closures, closures); + while !ctx.async_closures.is_empty() { - let closures = ctx.async_closures.clone(); + let async_closures = ctx.async_closures.clone(); ctx.async_closures.clear(); - let hir = cx.tcx.hir(); - for closure in closures { - if !checked_closures.insert(closure) { - continue; - } - ctx.prev_bind = None; - ctx.prev_move_to_closure.clear(); - if let Some(body) = hir - .find_by_def_id(closure) - .and_then(associated_body) - .map(|(_, body_id)| hir.body(body_id)) - { - euv::ExprUseVisitor::new(&mut ctx, &infcx, closure, cx.param_env, cx.typeck_results()) - .consume_body(body); - } - } + check_closures(&mut ctx, cx, &infcx, &mut checked_closures, async_closures); } } ctx @@ -244,6 +268,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { struct MutablyUsedVariablesCtxt<'tcx> { mutably_used_vars: HirIdSet, prev_bind: Option, + /// In async functions, the inner AST is composed of multiple layers until we reach the code + /// defined by the user. Because of that, some variables are marked as mutably borrowed even + /// though they're not. This field lists the `HirId` that should not be considered as mutable + /// use of a variable. prev_move_to_closure: HirIdSet, aliases: HirIdMap, async_closures: FxHashSet, @@ -308,7 +336,12 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId, borrow: ty::BorrowKind) { self.prev_bind = None; if let euv::Place { - base: euv::PlaceBase::Local(vid), + base: + euv::PlaceBase::Local(vid) + | euv::PlaceBase::Upvar(UpvarId { + var_path: UpvarPath { hir_id: vid }, + .. + }), base_ty, .. } = &cmt.place 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 5ee26966fa716..6d7df2eac6291 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 @@ -4,7 +4,7 @@ use clippy_utils::source::{snippet, snippet_opt}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; -use clippy_utils::{get_trait_def_id, is_self, paths}; +use clippy_utils::is_self; use if_chain::if_chain; use rustc_ast::ast::Attribute; use rustc_errors::{Applicability, Diagnostic}; @@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { need!(cx.tcx.lang_items().fn_trait()), need!(cx.tcx.lang_items().fn_once_trait()), need!(cx.tcx.lang_items().fn_mut_trait()), - need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)), + need!(cx.tcx.get_diagnostic_item(sym::RangeBounds)), ]; let sized_trait = need!(cx.tcx.lang_items().sized_trait()); diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 5f2a324b05fb9..aee184252fbfd 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -5,10 +5,8 @@ use clippy_utils::{get_parent_node, is_lint_allowed, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, FnRetTy, ItemKind, Node, PatKind, Stmt, StmtKind, - UnsafeSource, + is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, ItemKind, Node, PatKind, Stmt, StmtKind, UnsafeSource, }; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -99,14 +97,13 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { |diag| { for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { if let Node::Item(item) = parent.1 - && let ItemKind::Fn(sig, ..) = item.kind - && let FnRetTy::Return(ret_ty) = sig.decl.output + && let ItemKind::Fn(..) = item.kind && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) && let [.., final_stmt] = block.stmts && final_stmt.hir_id == stmt.hir_id { let expr_ty = cx.typeck_results().expr_ty(expr); - let mut ret_ty = hir_ty_to_ty(cx.tcx, ret_ty); + let mut ret_ty = cx.tcx.fn_sig(item.owner_id).instantiate_identity().output().skip_binder(); // Remove `impl Future` to get `T` if cx.tcx.ty_is_opaque_future(ret_ty) && @@ -115,7 +112,7 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { ret_ty = true_ret_ty; } - if ret_ty == expr_ty { + if !ret_ty.is_unit() && ret_ty == expr_ty { diag.span_suggestion( stmt.span.shrink_to_lo(), "did you mean to return it?", diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 4b24f059afdf5..0e4b6aa1b7d23 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::paths::ORD_CMP; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, match_def_path, path_res, std_or_core}; +use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, path_res, std_or_core}; use rustc_errors::Applicability; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp}; +use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -103,7 +102,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub NON_CANONICAL_PARTIAL_ORD_IMPL, suspicious, "non-canonical implementation of `PartialOrd` on an `Ord` type" @@ -122,9 +121,6 @@ impl LateLintPass<'_> for NonCanonicalImpls { if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { return; } - let ItemKind::Impl(_) = item.kind else { - return; - }; let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { return; }; @@ -180,17 +176,8 @@ impl LateLintPass<'_> for NonCanonicalImpls { if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl.def_id) && impl_item.ident.name == sym::partial_cmp - && let Some(ord_def_id) = cx - .tcx - .diagnostic_items(trait_impl.def_id.krate) - .name_to_id - .get(&sym::Ord) - && implements_trait( - cx, - trait_impl.self_ty(), - *ord_def_id, - &[], - ) + && let Some(ord_def_id) = cx.tcx.get_diagnostic_item(sym::Ord) + && implements_trait(cx, trait_impl.self_ty(), ord_def_id, &[]) { // If the `cmp` call likely needs to be fully qualified in the suggestion // (like `std::cmp::Ord::cmp`). It's unfortunate we must put this here but we can't @@ -273,7 +260,7 @@ fn self_cmp_call<'tcx>( match cmp_expr.kind { ExprKind::Call(path, [_self, _other]) => path_res(cx, path) .opt_def_id() - .is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP)), + .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id)), ExprKind::MethodCall(_, _, [_other], ..) => { // We can set this to true here no matter what as if it's a `MethodCall` and goes to the // `else` branch, it must be a method named `cmp` that isn't `Ord::cmp` @@ -285,7 +272,7 @@ fn self_cmp_call<'tcx>( cx.tcx .typeck(def_id) .type_dependent_def_id(cmp_expr.hir_id) - .is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP)) + .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id)) }, _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 8846633378798..2b4e3260c56b1 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId; use rustc_hir::{ BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp, }; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId}; use rustc_middle::ty::adjustment::Adjust; @@ -297,8 +296,8 @@ declare_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTER impl<'tcx> LateLintPass<'tcx> for NonCopyConst { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) { - if let ItemKind::Const(hir_ty, _generics, body_id) = it.kind { - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + if let ItemKind::Const(.., body_id) = it.kind { + let ty = cx.tcx.type_of(it.owner_id).instantiate_identity(); if !ignored_macro(cx, it) && is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, body_id, ty) { lint(cx, Source::Item { item: it.span }); } @@ -306,8 +305,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Const(hir_ty, body_id_opt) = &trait_item.kind { - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + if let TraitItemKind::Const(_, body_id_opt) = &trait_item.kind { + let ty = cx.tcx.type_of(trait_item.owner_id).instantiate_identity(); // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound. @@ -333,7 +332,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { - if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind { + if let ImplItemKind::Const(_, body_id) = &impl_item.kind { let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(item_def_id); @@ -366,7 +365,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // we should use here as a frozen variant is a potential to be frozen // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); if is_unfrozen(cx, normalized); if is_value_unfrozen_poly(cx, *body_id, normalized); @@ -381,7 +380,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } }, ItemKind::Impl(Impl { of_trait: None, .. }) => { - let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); // Normalize assoc types originated from generic params. let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs index e1de494eb41c0..d47728f190ab9 100644 --- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_opt, snippet_with_applicability}; -use clippy_utils::ty::{is_type_diagnostic_item, match_type}; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; @@ -45,13 +44,12 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { match &expr.kind { ExprKind::MethodCall(path, func, [param], _) => { - let obj_ty = cx.typeck_results().expr_ty(func).peel_refs(); - if_chain! { + if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def(); if (path.ident.name == sym!(mode) - && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS) - || is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder))) - || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS)); + && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder))) + || (path.ident.name == sym!(set_mode) + && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())); if let ExprKind::Lit(_) = param.kind; if param.span.ctxt() == expr.span.ctxt(); diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index c5e777c207028..d388dfc08f3b7 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{is_lint_allowed, match_def_path, paths}; +use clippy_utils::is_lint_allowed; use rustc_ast::ImplPolarity; use rustc_hir::def_id::DefId; use rustc_hir::{FieldDef, Item, ItemKind, Node}; @@ -233,7 +233,7 @@ fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> b return true; }, ty::Adt(adt_def, _) => { - if match_def_path(cx, adt_def.did(), &paths::PTR_NON_NULL) { + if cx.tcx.is_diagnostic_item(sym::NonNull, adt_def.did()) { return true; } }, diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 8072aded8513b..a10aa65e59482 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -315,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id()); let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id); - if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind { + if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind { let body_span = cx.tcx.hir().span_with_body(body_owner); if let Some(span) = self.const_span && span.contains(body_span) { return; diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs index d3de9699fe9d9..136642d69dcaa 100644 --- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs +++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{match_def_path, path_def_id, paths}; +use clippy_utils::path_def_id; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::LateContext; @@ -50,7 +50,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) }, ExprKind::Call(path, [arg]) if path_def_id(cx, path).map_or(false, |did| { - if match_def_path(cx, did, &paths::FROM_STR_METHOD) { + if cx.tcx.is_diagnostic_item(sym::from_str_method, did) { true } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) { !is_copy(cx, typeck.expr_ty(expr)) diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 4635e1164cd31..6b247cf5f6ae1 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -312,7 +312,7 @@ declare_clippy_lint! { /// # let status_code = 200; /// if status_code <= 400 && status_code > 500 {} /// ``` - #[clippy::version = "1.71.0"] + #[clippy::version = "1.73.0"] pub IMPOSSIBLE_COMPARISONS, correctness, "double comparisons that will never evaluate to `true`" @@ -332,7 +332,7 @@ declare_clippy_lint! { /// # let status_code = 200; /// if status_code <= 400 && status_code < 500 {} /// ``` - #[clippy::version = "1.71.0"] + #[clippy::version = "1.73.0"] pub REDUNDANT_COMPARISONS, correctness, "double comparisons where one of them can be removed" diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs index 102845ceed095..80389cbf84be2 100644 --- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs @@ -72,7 +72,7 @@ impl Context { let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id()); match cx.tcx.hir().body_owner_kind(body_owner_def_id) { - hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => { + hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => { let body_span = cx.tcx.hir().span_with_body(body_owner); if let Some(span) = self.const_span { diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs index 664d44d6504dc..f3089d716ff1c 100644 --- a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs +++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::paths; -use clippy_utils::ty::match_type; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -31,7 +31,7 @@ declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALS impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind - && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS) + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions) && path.ident.name == sym!(set_readonly) && let ExprKind::Lit(lit) = &arg.kind && LitKind::Bool(false) == lit.node diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index bf031ac84549d..310051efc5088 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -4,9 +4,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; -use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths}; +use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local}; use hir::LifetimeName; -use if_chain::if_chain; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdMap; @@ -16,7 +15,6 @@ use rustc_hir::{ ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, }; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_lint::{LateContext, LateLintPass}; @@ -172,13 +170,8 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { for arg in check_fn_args( cx, - cx.tcx - .fn_sig(item.owner_id) - .instantiate_identity() - .skip_binder() - .inputs(), + cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder(), sig.decl.inputs, - &sig.decl.output, &[], ) .filter(|arg| arg.mutability() == Mutability::Not) @@ -237,7 +230,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { let decl = sig.decl; let sig = cx.tcx.fn_sig(item_id).instantiate_identity().skip_binder(); - let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, &decl.output, body.params) + let lint_args: Vec<_> = check_fn_args(cx, sig, decl.inputs, body.params) .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not) .collect(); let results = check_ptr_arg_usage(cx, body, &lint_args); @@ -277,60 +270,43 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B. - const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 13] = [ - (&paths::SLICE_FROM_RAW_PARTS, &[0]), - (&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]), - (&paths::PTR_COPY, &[0, 1]), - (&paths::PTR_COPY_NONOVERLAPPING, &[0, 1]), - (&paths::PTR_READ, &[0]), - (&paths::PTR_READ_UNALIGNED, &[0]), - (&paths::PTR_READ_VOLATILE, &[0]), - (&paths::PTR_REPLACE, &[0]), - (&paths::PTR_SLICE_FROM_RAW_PARTS, &[0]), - (&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]), - (&paths::PTR_SWAP, &[0, 1]), - (&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]), - (&paths::PTR_WRITE_BYTES, &[0]), - ]; - let invalid_null_ptr_usage_table_diag_items: [(Option, &[usize]); 3] = [ - (cx.tcx.get_diagnostic_item(sym::ptr_write), &[0]), - (cx.tcx.get_diagnostic_item(sym::ptr_write_unaligned), &[0]), - (cx.tcx.get_diagnostic_item(sym::ptr_write_volatile), &[0]), - ]; - - if_chain! { - if let ExprKind::Call(fun, args) = expr.kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::>(); - if let Some(arg_indices) = INVALID_NULL_PTR_USAGE_TABLE - .iter() - .find_map(|&(fn_path, indices)| if fn_path == fun_def_path { Some(indices) } else { None }) - .or_else(|| { - invalid_null_ptr_usage_table_diag_items - .iter() - .find_map(|&(def_id, indices)| { - if def_id == Some(fun_def_id) { - Some(indices) - } else { - None - } - }) - }); - then { - for &arg_idx in arg_indices { - if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) { - span_lint_and_sugg( - cx, - INVALID_NULL_PTR_USAGE, - arg.span, - "pointer must be non-null", - "change this to", - "core::ptr::NonNull::dangling().as_ptr()".to_string(), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Call(fun, args) = expr.kind + && let ExprKind::Path(ref qpath) = fun.kind + && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() + && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id) + { + // `arg` positions where null would cause U.B. + let arg_indices: &[_] = match name { + sym::ptr_read + | sym::ptr_read_unaligned + | sym::ptr_read_volatile + | sym::ptr_replace + | sym::ptr_slice_from_raw_parts + | sym::ptr_slice_from_raw_parts_mut + | sym::ptr_write + | sym::ptr_write_bytes + | sym::ptr_write_unaligned + | sym::ptr_write_volatile + | sym::slice_from_raw_parts + | sym::slice_from_raw_parts_mut => &[0], + sym::ptr_copy + | sym::ptr_copy_nonoverlapping + | sym::ptr_swap + | sym::ptr_swap_nonoverlapping => &[0, 1], + _ => return, + }; + + for &arg_idx in arg_indices { + if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) { + span_lint_and_sugg( + cx, + INVALID_NULL_PTR_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + "core::ptr::NonNull::dangling().as_ptr()".to_string(), + Applicability::MachineApplicable, + ); } } } @@ -443,12 +419,13 @@ impl<'tcx> DerefTy<'tcx> { #[expect(clippy::too_many_lines)] fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, - tys: &'tcx [Ty<'tcx>], + fn_sig: ty::FnSig<'tcx>, hir_tys: &'tcx [hir::Ty<'tcx>], - ret_ty: &'tcx FnRetTy<'tcx>, params: &'tcx [Param<'tcx>], ) -> impl Iterator> + 'cx { - tys.iter() + fn_sig + .inputs() + .iter() .zip(hir_tys.iter()) .enumerate() .filter_map(move |(i, (ty, hir_ty))| { @@ -494,9 +471,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }) { if !lifetime.is_anonymous() - && let FnRetTy::Return(ret_ty) = ret_ty - && let ret_ty = hir_ty_to_ty(cx.tcx, ret_ty) - && ret_ty + && fn_sig.output() .walk() .filter_map(|arg| { arg.as_region().and_then(|lifetime| { diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index e8018462d75f6..c951d9a4a09d5 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub NEEDLESS_RAW_STRING_HASHES, - style, + pedantic, "suggests reducing the number of hashes around a raw string literal" } impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]); @@ -75,6 +75,7 @@ impl EarlyLintPass for RawStrings { if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) { return; } + let descr = lit.kind.descr(); if !str.contains(['\\', '"']) { span_lint_and_then( @@ -89,24 +90,22 @@ impl EarlyLintPass for RawStrings { let r_pos = expr.span.lo() + BytePos::from_usize(prefix.len() - 1); let start = start.with_lo(r_pos); - if end.is_empty() { - diag.span_suggestion( - start, - "use a string literal instead", - format!("\"{}\"", str), - Applicability::MachineApplicable, - ); - } else { - diag.multipart_suggestion( - "try", - vec![(start, String::new()), (end, String::new())], - Applicability::MachineApplicable, - ); + let mut remove = vec![(start, String::new())]; + // avoid debug ICE from empty suggestions + if !end.is_empty() { + remove.push((end, String::new())); } + + diag.multipart_suggestion_verbose( + format!("use a plain {descr} literal instead"), + remove, + Applicability::MachineApplicable, + ); }, ); - - return; + if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) { + return; + } } let req = { @@ -148,9 +147,9 @@ impl EarlyLintPass for RawStrings { let (start, end) = hash_spans(expr.span, prefix, req, max); let message = match max - req { - _ if req == 0 => "remove all the hashes around the literal".to_string(), - 1 => "remove one hash from both sides of the literal".to_string(), - n => format!("remove {n} hashes from both sides of the literal"), + _ if req == 0 => format!("remove all the hashes around the {descr} literal"), + 1 => format!("remove one hash from both sides of the {descr} literal"), + n => format!("remove {n} hashes from both sides of the {descr} literal"), }; diag.multipart_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs index 8e85c55e7563f..1a127c2bcf68e 100644 --- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs @@ -2,11 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::VecArgs; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::{indent_of, snippet}; -use clippy_utils::ty::match_type; -use clippy_utils::{last_path_segment, paths}; +use clippy_utils::last_path_segment; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, Span, Symbol}; @@ -133,8 +133,9 @@ fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> { return Some((symbol, func.span)); } - let ty_path = cx.typeck_results().expr_ty(expr); - if match_type(cx, ty_path, &paths::WEAK_RC) || match_type(cx, ty_path, &paths::WEAK_ARC) { + if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind() + && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak)) + { return Some((Symbol::intern("Weak"), func.span)); } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index e36adef555e65..2c0086b09813c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -99,8 +99,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD) - || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD) - || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD) + || cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id) + || (cx.tcx.is_diagnostic_item(sym::to_string_method, fn_def_id) && is_type_lang_item(cx, arg_ty, LangItem::String)); let from_deref = !from_borrow diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index fc49b58e0a777..f42836611ca53 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -10,6 +10,7 @@ use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -84,7 +85,7 @@ fn find_innermost_closure<'tcx>( cx: &LateContext<'tcx>, mut expr: &'tcx hir::Expr<'tcx>, mut steps: usize, -) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> { +) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, ty::Asyncness)> { let mut data = None; while let hir::ExprKind::Closure(closure) = expr.kind @@ -98,9 +99,9 @@ fn find_innermost_closure<'tcx>( { expr = body.value; data = Some((body.value, closure.fn_decl, if is_async_closure(body) { - hir::IsAsync::Async + ty::Asyncness::Yes } else { - hir::IsAsync::NotAsync + ty::Asyncness::No })); steps -= 1; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index 0c89c7ee47d36..197742b5dd41d 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -3,11 +3,9 @@ use clippy_utils::is_from_proc_macro; use clippy_utils::ty::needs_ordered_drop; use rustc_ast::Mutability; use rustc_hir::def::Res; -use rustc_hir::{ - BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath, -}; +use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, Local, Node, Pat, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::{in_external_macro, is_from_async_await}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Ident; use rustc_span::DesugaringKind; @@ -39,7 +37,7 @@ declare_clippy_lint! { /// // no redefinition with the same name /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub REDUNDANT_LOCALS, correctness, "redundant redefinition of a local binding" @@ -68,21 +66,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { // the local does not change the effect of assignments to the binding. see #11290 if !affects_assignments(cx, mutability, binding_id, local.hir_id); // the local does not affect the code's drop behavior - if !affects_drop_behavior(cx, binding_id, local.hir_id, expr); + if !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr)); // the local is user-controlled if !in_external_macro(cx.sess(), local.span); if !is_from_proc_macro(cx, expr); - // Async function parameters are lowered into the closure body, so we can't lint them. - // see `lower_maybe_async_body` in `rust_ast_lowering` - if !is_from_async_await(local.span); then { span_lint_and_help( cx, REDUNDANT_LOCALS, - vec![binding_pat.span, local.span], - "redundant redefinition of a binding", - None, - &format!("remove the redefinition of `{ident}`"), + local.span, + &format!("redundant redefinition of a binding `{ident}`"), + Some(binding_pat.span), + &format!("`{ident}` is initially defined here"), ); } } @@ -109,18 +104,3 @@ fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId // the binding is mutable and the rebinding is in a different scope than the original binding mutability == Mutability::Mut && hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind) } - -/// Check if a rebinding of a local affects the code's drop behavior. -fn affects_drop_behavior<'tcx>( - cx: &LateContext<'tcx>, - bind: HirId, - rebind: HirId, - rebind_expr: &Expr<'tcx>, -) -> bool { - let hir = cx.tcx.hir(); - - // the rebinding is in a different scope than the original binding - // and the type of the binding cares about drop order - hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind) - && needs_ordered_drop(cx, cx.typeck_results().expr_ty(rebind_expr)) -} diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index bd783b4e00541..b940cac6047be 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -2,7 +2,6 @@ //! expecting a count of T use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -67,16 +66,6 @@ fn get_pointee_ty_and_count_expr<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> { - const FUNCTIONS: [&[&str]; 8] = [ - &paths::PTR_COPY_NONOVERLAPPING, - &paths::PTR_COPY, - &paths::PTR_WRITE_BYTES, - &paths::PTR_SWAP_NONOVERLAPPING, - &paths::PTR_SLICE_FROM_RAW_PARTS, - &paths::PTR_SLICE_FROM_RAW_PARTS_MUT, - &paths::SLICE_FROM_RAW_PARTS, - &paths::SLICE_FROM_RAW_PARTS_MUT, - ]; const METHODS: [&str; 11] = [ "write_bytes", "copy_to", @@ -97,7 +86,16 @@ fn get_pointee_ty_and_count_expr<'tcx>( if let ExprKind::Call(func, [.., count]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path)); + if matches!(cx.tcx.get_diagnostic_name(def_id), Some( + sym::ptr_copy + | sym::ptr_copy_nonoverlapping + | sym::ptr_slice_from_raw_parts + | sym::ptr_slice_from_raw_parts_mut + | sym::ptr_swap_nonoverlapping + | sym::ptr_write_bytes + | sym::slice_from_raw_parts + | sym::slice_from_raw_parts_mut + )); // Get the pointee type if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next(); diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 5f54a10d1c41d..b7396535eedff 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -1,9 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_from_proc_macro; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::{HirId, Path, PathSegment}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; @@ -99,6 +101,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { if let Res::Def(_, def_id) = path.res && let Some(first_segment) = get_first_segment(path) && is_stable(cx, def_id) + && !in_external_macro(cx.sess(), path.span) + && !is_from_proc_macro(cx, &first_segment.ident) { let (lint, used_mod, replace_with) = match first_segment.ident.name { sym::std => match cx.tcx.crate_name(def_id.krate) { diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs index d085dda3582be..3685432a25399 100644 --- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_context; -use clippy_utils::{match_def_path, path_def_id, paths}; +use clippy_utils::path_def_id; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{Span, SyntaxContext}; +use rustc_span::{sym, Span, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -42,7 +42,7 @@ impl LateLintPass<'_> for SwapPtrToRef { fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { if let ExprKind::Call(fn_expr, [arg1, arg2]) = e.kind && let Some(fn_id) = path_def_id(cx, fn_expr) - && match_def_path(cx, fn_id, &paths::MEM_SWAP) + && cx.tcx.is_diagnostic_item(sym::mem_swap, fn_id) && let ctxt = e.span.ctxt() && let (from_ptr1, arg1_span) = is_ptr_to_ref(cx, arg1, ctxt) && let (from_ptr2, arg2_span) = is_ptr_to_ref(cx, arg2, ctxt) diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs index 4944381da24d5..b26365e34ab94 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs @@ -28,35 +28,43 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t return false; } - match arg.kind { + let casts_peeled = peel_casts(arg); + match casts_peeled.kind { // Catching: // transmute over constants that resolve to `null`. - ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => { + ExprKind::Path(ref _qpath) + if matches!( + constant(cx, cx.typeck_results(), casts_peeled), + Some(Constant::RawPtr(0)) + ) => + { lint_expr(cx, expr); true }, - - // Catching: - // `std::mem::transmute(0 as *const i32)` - ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => { - lint_expr(cx, expr); - true - }, - // Catching: // `std::mem::transmute(std::ptr::null::())` ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => { lint_expr(cx, expr); true }, - _ => { // FIXME: // Also catch transmutations of variables which are known nulls. // To do this, MIR const propagation seems to be the better tool. // Whenever MIR const prop routines are more developed, this will // become available. As of this writing (25/03/19) it is not yet. + if is_integer_literal(casts_peeled, 0) { + lint_expr(cx, expr); + return true; + } false }, } } + +fn peel_casts<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + match &expr.kind { + ExprKind::Cast(inner_expr, _) => peel_casts(inner_expr), + _ => expr, + } +} diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 79f9d45d597ef..71a4b3fba1b59 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -315,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( &mut self, cx: &LateContext<'_>, - _: FnKind<'_>, + fn_kind: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, @@ -340,6 +340,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { CheckTyContext { is_in_trait_impl, is_exported, + in_body: matches!(fn_kind, FnKind::Closure), ..CheckTyContext::default() }, ); @@ -427,7 +428,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { cx, ty, CheckTyContext { - is_local: true, + in_body: true, ..CheckTyContext::default() }, ); @@ -481,7 +482,7 @@ impl Types { } match hir_ty.kind { - TyKind::Path(ref qpath) if !context.is_local => { + TyKind::Path(ref qpath) if !context.in_body => { let hir_id = hir_ty.hir_id; let res = cx.qpath_res(qpath, hir_id); if let Some(def_id) = res.opt_def_id() { @@ -581,8 +582,8 @@ impl Types { #[derive(Clone, Copy, Default)] struct CheckTyContext { is_in_trait_impl: bool, - /// `true` for types on local variables. - is_local: bool, + /// `true` for types on local variables and in closure signatures. + in_body: bool, /// `true` for types that are part of the public API. is_exported: bool, is_nested_call: bool, diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index 704d7abd7e55a..e7915953d85b3 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, Local, MatchSource, Node, PatKind, QPath, TyKind}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; +use rustc_middle::lint::{in_external_macro, is_from_async_await}; use rustc_middle::ty; use super::LET_UNIT_VALUE; @@ -16,6 +16,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { if let Some(init) = local.init && !local.pat.span.from_expansion() && !in_external_macro(cx.sess(), local.span) + && !is_from_async_await(local.span) && cx.typeck_results().pat_ty(local.pat).is_unit() { if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer)) diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs index dea8a1e35bbba..996e7edf5573d 100644 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -96,7 +96,7 @@ impl LateLintPass<'_> for UnnamedAddress { if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::PTR_EQ); + if cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id); let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0); if ty_param.is_trait(); then { diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs new file mode 100644 index 0000000000000..5aa057580e9d9 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -0,0 +1,93 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::get_type_diagnostic_name; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Suggest removing the use of a may (or map_err) method when an Option or Result is being construted. + /// + /// ### Why is this bad? + /// It introduces unnecessary complexity. In this case the function can be used directly and + /// construct the Option or Result from the output. + /// + /// ### Example + /// ```rust + /// Some(4).map(i32::swap_bytes); + /// ``` + /// Use instead: + /// ```rust + /// Some(i32::swap_bytes(4)); + /// ``` + #[clippy::version = "1.73.0"] + pub UNNECESSARY_MAP_ON_CONSTRUCTOR, + complexity, + "using `map`/`map_err` on `Option` or `Result` constructors" +} +declare_lint_pass!(UnnecessaryMapOnConstructor => [UNNECESSARY_MAP_ON_CONSTRUCTOR]); + +impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + if expr.span.from_expansion() { + return; + } + if let hir::ExprKind::MethodCall(path, recv, args, ..) = expr.kind + && let Some(sym::Option | sym::Result) = get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(recv)){ + let (constructor_path, constructor_item) = + if let hir::ExprKind::Call(constructor, constructor_args) = recv.kind + && let hir::ExprKind::Path(constructor_path) = constructor.kind + && let Some(arg) = constructor_args.get(0) + { + if constructor.span.from_expansion() || arg.span.from_expansion() { + return; + } + (constructor_path, arg) + } else { + return; + }; + let constructor_symbol = match constructor_path { + hir::QPath::Resolved(_, path) => { + if let Some(path_segment) = path.segments.last() { + path_segment.ident.name + } else { + return; + } + }, + hir::QPath::TypeRelative(_, path) => path.ident.name, + hir::QPath::LangItem(_, _, _) => return, + }; + match constructor_symbol { + sym::Some | sym::Ok if path.ident.name == rustc_span::sym::map => (), + sym::Err if path.ident.name == sym!(map_err) => (), + _ => return, + } + + if let Some(map_arg) = args.get(0) + && let hir::ExprKind::Path(fun) = map_arg.kind + { + if map_arg.span.from_expansion() { + return; + } + let mut applicability = Applicability::MachineApplicable; + let fun_snippet = snippet_with_applicability(cx, fun.span(), "_", &mut applicability); + let constructor_snippet = + snippet_with_applicability(cx, constructor_path.span(), "_", &mut applicability); + let constructor_arg_snippet = + snippet_with_applicability(cx, constructor_item.span, "_", &mut applicability); + span_lint_and_sugg( + cx, + UNNECESSARY_MAP_ON_CONSTRUCTOR, + expr.span, + &format!("unnecessary {} on constructor {constructor_snippet}(_)", path.ident.name), + "try", + format!("{constructor_snippet}({fun_snippet}({constructor_arg_snippet}))"), + applicability, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs index 4ee16d9a5e4ad..db91beec0efa7 100644 --- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs +++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::ty::{match_type, peel_mid_ty_refs_is_mutable}; -use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators}; +use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable}; +use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators}; use rustc_ast::Mutability; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind}; @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { // Don't lint `Peekable`s returned from a block if let Some(expr) = block.expr && let Some(ty) = cx.typeck_results().expr_ty_opt(peel_ref_operators(cx, expr)) - && match_type(cx, ty, &paths::PEEKABLE) + && is_type_diagnostic_item(cx, ty, sym::IterPeekable) { return; } @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { && !init.span.from_expansion() && let Some(ty) = cx.typeck_results().expr_ty_opt(init) && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty) - && match_type(cx, ty, &paths::PEEKABLE) + && is_type_diagnostic_item(cx, ty, sym::IterPeekable) { let mut vis = PeekableVisitor::new(cx, binding); @@ -222,7 +222,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { fn arg_is_mut_peekable(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool { if let Some(ty) = cx.typeck_results().expr_ty_opt(arg) && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty) - && match_type(cx, ty, &paths::PEEKABLE) + && is_type_diagnostic_item(cx, ty, sym::IterPeekable) { true } else { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 5ac4f0aa46c10..3cc91838c0004 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -2,16 +2,20 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; -use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths}; +use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, path_to_local}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::Obligation; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; declare_clippy_lint! { /// ### What it does @@ -61,22 +65,69 @@ impl MethodOrFunction { } } -/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` -fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option { - cx.tcx - .predicates_of(fn_did) - .predicates - .iter() - .find_map(|&(ref pred, span)| { - if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() - && tr.def_id() == into_iter_did - && tr.self_ty().is_param(param_index) - { - Some(span) - } else { - None +/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did`, +/// iff all of the bounds also hold for the type of the `.into_iter()` receiver. +/// ```ignore +/// pub fn foo(i: I) +/// where I: IntoIterator + ExactSizeIterator +/// ^^^^^^^^^^^^^^^^^ this extra bound stops us from suggesting to remove `.into_iter()` ... +/// { +/// assert_eq!(i.len(), 3); +/// } +/// +/// pub fn bar() { +/// foo([1, 2, 3].into_iter()); +/// ^^^^^^^^^^^^ ... here, because `[i32; 3]` is not `ExactSizeIterator` +/// } +/// ``` +fn into_iter_bound<'tcx>( + cx: &LateContext<'tcx>, + fn_did: DefId, + into_iter_did: DefId, + into_iter_receiver: Ty<'tcx>, + param_index: u32, + node_args: GenericArgsRef<'tcx>, +) -> Option { + let param_env = cx.tcx.param_env(fn_did); + let mut into_iter_span = None; + + for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates { + if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() { + if tr.self_ty().is_param(param_index) { + if tr.def_id() == into_iter_did { + into_iter_span = Some(*span); + } else { + let tr = cx.tcx.erase_regions(tr); + if tr.has_escaping_bound_vars() { + return None; + } + + // Substitute generics in the predicate and replace the IntoIterator type parameter with the + // `.into_iter()` receiver to see if the bound also holds for that type. + let args = cx.tcx.mk_args_from_iter(node_args.iter().enumerate().map(|(i, arg)| { + if i == param_index as usize { + GenericArg::from(into_iter_receiver) + } else { + arg + } + })); + + let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), param_env, predicate); + if !cx + .tcx + .infer_ctxt() + .build() + .predicate_must_hold_modulo_regions(&obligation) + { + return None; + } + } } - }) + } + } + + into_iter_span } /// Extracts the receiver of a `.into_iter()` method call. @@ -160,22 +211,41 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { // `fn_sig` does not ICE. (see #11065) && cx.tcx.opt_def_kind(did).is_some_and(DefKind::is_fn_like) => { - Some((did, args, MethodOrFunction::Function)) + Some(( + did, + args, + cx.typeck_results().node_args(recv.hir_id), + MethodOrFunction::Function + )) } ExprKind::MethodCall(.., args, _) => { cx.typeck_results().type_dependent_def_id(parent.hir_id) - .map(|did| (did, args, MethodOrFunction::Method)) + .map(|did| { + return ( + did, + args, + cx.typeck_results().node_args(parent.hir_id), + MethodOrFunction::Method + ); + }) } _ => None, }; - if let Some((parent_fn_did, args, kind)) = parent_fn + if let Some((parent_fn_did, args, node_args, kind)) = parent_fn && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() && let Some(arg_pos) = args.iter().position(|x| x.hir_id == e.hir_id) && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) && let ty::Param(param) = into_iter_param.kind() - && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) + && let Some(span) = into_iter_bound( + cx, + parent_fn_did, + into_iter_did, + cx.typeck_results().expr_ty(into_iter_recv), + param.index, + node_args + ) && self.expn_depth == 0 { // Get the "innermost" `.into_iter()` call, e.g. given this expression: @@ -261,7 +331,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(arg); if_chain! { - if match_def_path(cx, def_id, &paths::TRY_FROM); + if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id); if is_type_diagnostic_item(cx, a, sym::Result); if let ty::Adt(_, args) = a.kind(); if let Some(a_type) = args.types().next(); diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 2688947552253..23da1de77303e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -294,7 +294,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE. /// /// The minimum rust version that the project supports (msrv: Option = None), @@ -542,11 +542,11 @@ define_Conf! { /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. /// /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block - (accept_comment_above_statement: bool = false), + (accept_comment_above_statement: bool = true), /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. /// /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block - (accept_comment_above_attributes: bool = false), + (accept_comment_above_attributes: bool = true), /// Lint: UNNECESSARY_RAW_STRING_HASHES. /// /// Whether to allow `r#""#` when `r""` can be used @@ -561,6 +561,11 @@ define_Conf! { /// Which crates to allow absolute paths from (absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet = rustc_data_structures::fx::FxHashSet::default()), + /// Lint: PATH_ENDS_WITH_EXT. + /// + /// Additional dotfiles (files or directories starting with a dot) to allow + (allowed_dotfiles: rustc_data_structures::fx::FxHashSet = + rustc_data_structures::fx::FxHashSet::default()), /// Lint: EXPLICIT_ITER_LOOP /// /// Whether to recommend using implicit into iter for reborrowed values. @@ -739,3 +744,44 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec) { (rows, column_widths) } + +#[cfg(test)] +mod tests { + use rustc_data_structures::fx::{FxHashMap, FxHashSet}; + use serde::de::IgnoredAny; + use std::fs; + use walkdir::WalkDir; + + #[test] + fn configs_are_tested() { + let mut names: FxHashSet = super::metadata::get_configuration_metadata() + .into_iter() + .map(|meta| meta.name.replace('_', "-")) + .collect(); + + let toml_files = WalkDir::new("../tests") + .into_iter() + .map(Result::unwrap) + .filter(|entry| entry.file_name() == "clippy.toml"); + + for entry in toml_files { + let file = fs::read_to_string(entry.path()).unwrap(); + #[allow(clippy::zero_sized_map_values)] + if let Ok(map) = toml::from_str::>(&file) { + for name in map.keys() { + names.remove(name.as_str()); + } + } + } + + assert!( + names.remove("allow-one-hash-in-raw-strings"), + "remove this when #11481 is fixed" + ); + + assert!( + names.is_empty(), + "Configuration variable lacks test: {names:?}\nAdd a test to `tests/ui-toml`" + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs index 6d3493523e6fc..94a9a7c241bb7 100644 --- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs @@ -1,12 +1,15 @@ -use clippy_utils::macros::collect_ast_format_args; +use clippy_utils::macros::AST_FORMAT_ARGS; use clippy_utils::source::snippet_opt; use itertools::Itertools; -use rustc_ast::{Expr, ExprKind, FormatArgs}; +use rustc_ast::{Crate, Expr, ExprKind, FormatArgs}; +use rustc_data_structures::fx::FxHashMap; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::hygiene; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{hygiene, Span}; use std::iter::once; +use std::mem; +use std::rc::Rc; declare_clippy_lint! { /// ### What it does @@ -17,7 +20,12 @@ declare_clippy_lint! { "collects `format_args` AST nodes for use in later lints" } -declare_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]); +#[derive(Default)] +pub struct FormatArgsCollector { + format_args: FxHashMap>, +} + +impl_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]); impl EarlyLintPass for FormatArgsCollector { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { @@ -26,9 +34,17 @@ impl EarlyLintPass for FormatArgsCollector { return; } - collect_ast_format_args(expr.span, args); + self.format_args + .insert(expr.span.with_parent(None), Rc::new((**args).clone())); } } + + fn check_crate_post(&mut self, _: &EarlyContext<'_>, _: &Crate) { + AST_FORMAT_ARGS.with(|ast_format_args| { + let result = ast_format_args.set(mem::take(&mut self.format_args)); + debug_assert!(result.is_ok()); + }); + } } /// Detects if the format string or an argument has its span set by a proc macro to something inside diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index da8654d9388d3..82f9d4e41e882 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -10,7 +10,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::mir::ConstValue; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Symbol; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 4ed985f54d0e2..250772238853b 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -5,10 +5,9 @@ use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::Item; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, FloatTy}; +use rustc_middle::ty::FloatTy; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; @@ -34,25 +33,20 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { let mod_name = &cx.tcx.item_name(local_def_id.to_def_id()); if_chain! { if mod_name.as_str() == "paths"; - if let hir::ItemKind::Const(ty, _, body_id) = item.kind; - let ty = hir_ty_to_ty(cx.tcx, ty); - if let ty::Array(el_ty, _) = &ty.kind(); - if let ty::Ref(_, el_ty, _) = &el_ty.kind(); - if el_ty.is_str(); + if let hir::ItemKind::Const(.., body_id) = item.kind; let body = cx.tcx.hir().body(body_id); let typeck_results = cx.tcx.typeck_body(body_id); if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value); - let path: Vec<&str> = path + if let Some(path) = path .iter() .map(|x| { if let Constant::Str(s) = x { - s.as_str() + Some(s.as_str()) } else { - // We checked the type of the constant above - unreachable!() + None } }) - .collect(); + .collect::>>(); if !check_path(cx, &path[..]); then { span_lint(cx, INVALID_PATHS, item.span, "invalid path"); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 87380f14f9a4d..bbb5ade8b9f36 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -28,8 +28,8 @@ declare_clippy_lint! { /// know the name of the lint. /// /// ### Known problems - /// Only checks for lints associated using the - /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros. + /// Only checks for lints associated using the `declare_lint_pass!` and + /// `impl_lint_pass!` macros. /// /// ### Example /// ```rust,ignore diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index f49c3fadb0780..c38a3e81b0f72 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -31,7 +31,7 @@ use serde::{Serialize, Serializer}; use std::collections::{BTreeSet, BinaryHeap}; use std::fmt; use std::fmt::Write as _; -use std::fs::{self, OpenOptions}; +use std::fs::{self, File}; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; @@ -229,25 +229,10 @@ impl Drop for MetadataCollector { collect_renames(&mut lints); // Outputting json - if Path::new(JSON_OUTPUT_FILE).exists() { - fs::remove_file(JSON_OUTPUT_FILE).unwrap(); - } - let mut file = OpenOptions::new() - .write(true) - .create(true) - .open(JSON_OUTPUT_FILE) - .unwrap(); - writeln!(file, "{}", serde_json::to_string_pretty(&lints).unwrap()).unwrap(); + fs::write(JSON_OUTPUT_FILE, serde_json::to_string_pretty(&lints).unwrap()).unwrap(); // Outputting markdown - if Path::new(MARKDOWN_OUTPUT_FILE).exists() { - fs::remove_file(MARKDOWN_OUTPUT_FILE).unwrap(); - } - let mut file = OpenOptions::new() - .write(true) - .create(true) - .open(MARKDOWN_OUTPUT_FILE) - .unwrap(); + let mut file = File::create(MARKDOWN_OUTPUT_FILE).unwrap(); writeln!( file, "") { - // I know this is kinda wasteful, we just don't have regex on `clippy_lints` so... this is the best - // we can do AFAIK. - changelog = changelog[..position].to_string(); - } + let changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap(); + let mut changelog_file = File::create(CHANGELOG_PATH).unwrap(); + let position = changelog + .find("") + .unwrap(); writeln!( changelog_file, - "{changelog}\n{}\n", + "{}\n{}\n", + &changelog[..position], self.configs_to_markdown(ClippyConfiguration::to_markdown_link) ) .unwrap(); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs index bf835f89cfc7f..86b77a77f1730 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -5,9 +5,8 @@ use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{self, GenericArgKind}; +use rustc_middle::ty::{self, EarlyBinder, GenericArgKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -25,16 +24,14 @@ impl LateLintPass<'_> for MsrvAttrImpl { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if_chain! { if let hir::ItemKind::Impl(hir::Impl { - of_trait: Some(lint_pass_trait_ref), - self_ty, + of_trait: Some(_), items, .. }) = &item.kind; - if let Some(lint_pass_trait_def_id) = lint_pass_trait_ref.trait_def_id(); - let is_late_pass = match_def_path(cx, lint_pass_trait_def_id, &paths::LATE_LINT_PASS); - if is_late_pass || match_def_path(cx, lint_pass_trait_def_id, &paths::EARLY_LINT_PASS); - let self_ty = hir_ty_to_ty(cx.tcx, self_ty); - if let ty::Adt(self_ty_def, _) = self_ty.kind(); + if let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::instantiate_identity); + let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS); + if is_late_pass || match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS); + if let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind(); if self_ty_def.is_struct(); if self_ty_def.all_fields().any(|f| { cx.tcx diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 4a5b6fa5c18d6..a3acb8f1762d8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -10,7 +10,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, Local, Mutability, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc}; +use rustc_middle::mir::interpret::{Allocation, GlobalAlloc}; +use rustc_middle::mir::ConstValue; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Symbol; @@ -232,7 +233,8 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option match cx.tcx.const_eval_poly(def_id).ok()? { - ConstValue::Indirect { alloc, offset } if offset.bytes() == 0 => { + ConstValue::Indirect { alloc_id, offset } if offset.bytes() == 0 => { + let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory(); read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id).instantiate_identity()) }, _ => None, diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index d09d02a7dfda9..70b83149ce1a6 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -132,6 +132,7 @@ impl LateLintPass<'_> for WildcardImports { if self.warn_on_all || !self.check_exceptions(item, use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id); if !used_imports.is_empty(); // Already handled by `unused_imports` + if !used_imports.contains(&kw::Underscore); then { let mut applicability = Applicability::MachineApplicable; let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index a9957b18a53b3..855aefa70cb15 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -3,12 +3,15 @@ use clippy_utils::macros::{find_format_args, format_arg_removal_span, root_macro use clippy_utils::source::{expand_past_previous_comma, snippet_opt}; use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_ast::token::LitKind; -use rustc_ast::{FormatArgPosition, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, FormatTrait}; +use rustc_ast::{ + FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, + FormatTrait, +}; use rustc_errors::Applicability; use rustc_hir::{Expr, Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{sym, BytePos}; +use rustc_span::{sym, BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -304,7 +307,7 @@ impl<'tcx> LateLintPass<'tcx> for Write { _ => return, } - find_format_args(cx, expr, macro_call.expn, |format_args| { + if let Some(format_args) = find_format_args(cx, expr, macro_call.expn) { // ignore `writeln!(w)` and `write!(v, some_macro!())` if format_args.span.from_expansion() { return; @@ -312,15 +315,15 @@ impl<'tcx> LateLintPass<'tcx> for Write { match diag_name { sym::print_macro | sym::eprint_macro | sym::write_macro => { - check_newline(cx, format_args, ¯o_call, name); + check_newline(cx, &format_args, ¯o_call, name); }, sym::println_macro | sym::eprintln_macro | sym::writeln_macro => { - check_empty_string(cx, format_args, ¯o_call, name); + check_empty_string(cx, &format_args, ¯o_call, name); }, _ => {}, } - check_literal(cx, format_args, name); + check_literal(cx, &format_args, name); if !self.in_debug_impl { for piece in &format_args.template { @@ -334,7 +337,7 @@ impl<'tcx> LateLintPass<'tcx> for Write { } } } - }); + } } } @@ -450,6 +453,12 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { let arg_index = |argument: &FormatArgPosition| argument.index.unwrap_or_else(|pos| pos); + let lint_name = if name.starts_with("write") { + WRITE_LITERAL + } else { + PRINT_LITERAL + }; + let mut counts = vec![0u32; format_args.arguments.all_args().len()]; for piece in &format_args.template { if let FormatArgsPiece::Placeholder(placeholder) = piece { @@ -457,6 +466,12 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { } } + let mut suggestion: Vec<(Span, String)> = vec![]; + // holds index of replaced positional arguments; used to decrement the index of the remaining + // positional arguments. + let mut replaced_position: Vec = vec![]; + let mut sug_span: Option = None; + for piece in &format_args.template { if let FormatArgsPiece::Placeholder(FormatPlaceholder { argument, @@ -471,9 +486,9 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { && let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind && !arg.expr.span.from_expansion() && let Some(value_string) = snippet_opt(cx, arg.expr.span) - { + { let (replacement, replace_raw) = match lit.kind { - LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) { + LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) { Some(extracted) => extracted, None => return, }, @@ -493,12 +508,6 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { _ => continue, }; - let lint = if name.starts_with("write") { - WRITE_LITERAL - } else { - PRINT_LITERAL - }; - let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else { continue }; let format_string_is_raw = format_string_snippet.starts_with('r'); @@ -519,29 +528,58 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { }, }; - span_lint_and_then( - cx, - lint, - arg.expr.span, - "literal with an empty format string", - |diag| { - if let Some(replacement) = replacement - // `format!("{}", "a")`, `format!("{named}", named = "b") - // ~~~~~ ~~~~~~~~~~~~~ - && let Some(removal_span) = format_arg_removal_span(format_args, index) - { - let replacement = replacement.replace('{', "{{").replace('}', "}}"); - diag.multipart_suggestion( - "try", - vec![(*placeholder_span, replacement), (removal_span, String::new())], - Applicability::MachineApplicable, - ); - } - }, - ); + sug_span = Some(sug_span.unwrap_or(arg.expr.span).to(arg.expr.span)); + if let Some((_, index)) = positional_arg_piece_span(piece) { + replaced_position.push(index); + } + + if let Some(replacement) = replacement + // `format!("{}", "a")`, `format!("{named}", named = "b") + // ~~~~~ ~~~~~~~~~~~~~ + && let Some(removal_span) = format_arg_removal_span(format_args, index) { + let replacement = escape_braces(&replacement, !format_string_is_raw && !replace_raw); + suggestion.push((*placeholder_span, replacement)); + suggestion.push((removal_span, String::new())); + } + } + } + + // Decrement the index of the remaining by the number of replaced positional arguments + if !suggestion.is_empty() { + for piece in &format_args.template { + if let Some((span, index)) = positional_arg_piece_span(piece) + && suggestion.iter().all(|(s, _)| *s != span) { + let decrement = replaced_position.iter().filter(|i| **i < index).count(); + suggestion.push((span, format!("{{{}}}", index.saturating_sub(decrement)))); + } } } + + if let Some(span) = sug_span { + span_lint_and_then(cx, lint_name, span, "literal with an empty format string", |diag| { + if !suggestion.is_empty() { + diag.multipart_suggestion("try", suggestion, Applicability::MachineApplicable); + } + }); + } +} + +/// Extract Span and its index from the given `piece`, iff it's positional argument. +fn positional_arg_piece_span(piece: &FormatArgsPiece) -> Option<(Span, usize)> { + match piece { + FormatArgsPiece::Placeholder(FormatPlaceholder { + argument: + FormatArgPosition { + index: Ok(index), + kind: FormatArgPositionKind::Number, + .. + }, + span: Some(span), + .. + }) => Some((*span, *index)), + _ => None, + } } /// Removes the raw marker, `#`s and quotes from a str, and returns if the literal is raw @@ -593,3 +631,47 @@ fn conservative_unescape(literal: &str) -> Result { if err { Err(UnescapeErr::Lint) } else { Ok(unescaped) } } + +/// Replaces `{` with `{{` and `}` with `}}`. If `preserve_unicode_escapes` is `true` the braces in +/// `\u{xxxx}` are left unmodified +#[expect(clippy::match_same_arms)] +fn escape_braces(literal: &str, preserve_unicode_escapes: bool) -> String { + #[derive(Clone, Copy)] + enum State { + Normal, + Backslash, + UnicodeEscape, + } + + let mut escaped = String::with_capacity(literal.len()); + let mut state = State::Normal; + + for ch in literal.chars() { + state = match (ch, state) { + // Escape braces outside of unicode escapes by doubling them up + ('{' | '}', State::Normal) => { + escaped.push(ch); + State::Normal + }, + // If `preserve_unicode_escapes` isn't enabled stay in `State::Normal`, otherwise: + // + // \u{aaaa} \\ \x01 + // ^ ^ ^ + ('\\', State::Normal) if preserve_unicode_escapes => State::Backslash, + // \u{aaaa} + // ^ + ('u', State::Backslash) => State::UnicodeEscape, + // \xAA \\ + // ^ ^ + (_, State::Backslash) => State::Normal, + // \u{aaaa} + // ^ + ('}', State::UnicodeEscape) => State::Normal, + _ => state, + }; + + escaped.push(ch); + } + + escaped +} diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 1596bb773976a..8522493f67b3a 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.74" +version = "0.1.75" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index c88fce22f7fb6..0bae7056c4fb8 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; -use rustc_middle::mir::interpret::Scalar; +use rustc_middle::mir::interpret::{alloc_range, Scalar}; use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; +use rustc_target::abi::Size; use std::cmp::Ordering::{self, Equal}; use std::hash::{Hash, Hasher}; use std::iter; @@ -21,7 +22,7 @@ use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] pub enum Constant<'tcx> { - Adt(rustc_middle::mir::ConstantKind<'tcx>), + Adt(rustc_middle::mir::Const<'tcx>), /// A `String` (e.g., "abc"). Str(String), /// A binary string (e.g., `b"abc"`). @@ -403,7 +404,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { && adt_def.is_struct() && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field) { - miri_to_const(self.lcx, desired_field) + mir_to_const(self.lcx, desired_field) } else { result @@ -482,8 +483,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None) .ok() - .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?; - let result = miri_to_const(self.lcx, result)?; + .map(|val| rustc_middle::mir::Const::from_value(val, ty))?; + let result = mir_to_const(self.lcx, result)?; self.source = ConstantSource::Constant; Some(result) }, @@ -655,10 +656,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option> { +pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option> { use rustc_middle::mir::ConstValue; - match result { - mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() { + let mir::Const::Val(val, _) = result else { + // We only work on evaluated consts. + return None; + }; + match (val, result.ty().kind()) { + (ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() { ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), @@ -671,41 +676,28 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), _ => None, }, - mir::ConstantKind::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) => { - let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?; + (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => { + let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?; String::from_utf8(data.to_owned()).ok().map(Constant::Str) - } - mir::ConstantKind::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => { - let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory(); - 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.try_to_target_usize(lcx.tcx) { - Some(len) => alloc - .inner() - .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) - .to_owned() - .array_chunks::<4>() - .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk)))) - .collect::>>>() - .map(Constant::Vec), - _ => None, - }, - 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())) - .to_owned() - .array_chunks::<8>() - .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk)))) - .collect::>>>() - .map(Constant::Vec), - _ => None, - }, - _ => None, - }, - _ => None, + }, + (_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)), + (ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => { + let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner(); + let len = len.try_to_target_usize(lcx.tcx)?; + let ty::Float(flt) = sub_type.kind() else { + return None; + }; + let size = Size::from_bits(flt.bit_width()); + let mut res = Vec::new(); + for idx in 0..len { + let range = alloc_range(offset + size * idx, size); + let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?; + res.push(match flt { + FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)), + FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)), + }); } + Some(Constant::Vec(res)) }, _ => None, } @@ -714,17 +706,17 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t fn field_of_struct<'tcx>( adt_def: ty::AdtDef<'tcx>, lcx: &LateContext<'tcx>, - result: mir::ConstantKind<'tcx>, + result: mir::Const<'tcx>, field: &Ident, -) -> Option> { - if let mir::ConstantKind::Val(result, ty) = result - && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty)) +) -> Option> { + if let mir::Const::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(&(val, ty)) = dc.fields.get(field_idx) { - Some(mir::ConstantKind::Val(val, ty)) + Some(mir::Const::Val(val, ty)) } else { None diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 802adbd4d2d56..741f9f54883d6 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -457,7 +457,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) - }; }, ExprKind::Path(QPath::Resolved(_, path)) - if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD) + if cx.tcx.is_diagnostic_item(sym::default_fn, path.res.opt_def_id()?) && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) => { return Some(VecInitKind::Default); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4ef3ec19647e9..c2c97259d38bf 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -80,7 +80,6 @@ use std::sync::{Mutex, MutexGuard, OnceLock}; use if_chain::if_chain; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; -use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; @@ -90,14 +89,14 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, - ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, + ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; -use rustc_middle::mir::ConstantKind; +use rustc_middle::mir::Const; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -113,7 +112,7 @@ use rustc_span::{sym, Span}; use rustc_target::abi::Integer; use visitors::Visitable; -use crate::consts::{constant, miri_to_const, Constant}; +use crate::consts::{constant, mir_to_const, Constant}; use crate::higher::Range; use crate::ty::{ adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, @@ -288,7 +287,7 @@ pub fn is_wild(pat: &Pat<'_>) -> bool { /// Checks if the given `QPath` belongs to a type alias. pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { match *qpath { - QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias { .. } | DefKind::AssocTy, ..)), + QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)), QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) }, _ => false, } @@ -1509,9 +1508,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) - && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree())) - && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty) - && let Some(min_const) = miri_to_const(cx, min_const_kind) + && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, cx.tcx)) && let Some(start_const) = constant(cx, cx.typeck_results(), start) { start_const == min_const @@ -1525,9 +1522,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) - && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree())) - && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty) - && let Some(max_const) = miri_to_const(cx, max_const_kind) + && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, cx.tcx)) && let Some(end_const) = constant(cx, cx.typeck_results(), end) { end_const == max_const @@ -1785,6 +1780,33 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc None } +/// Returns `true` if the lint is `#[allow]`ed or `#[expect]`ed at any of the `ids`, fulfilling all +/// of the expectations in `ids` +/// +/// This should only be used when the lint would otherwise be emitted, for a way to check if a lint +/// is allowed early to skip work see [`is_lint_allowed`] +/// +/// To emit at a lint at a different context than the one current see +/// [`span_lint_hir`](diagnostics::span_lint_hir) or +/// [`span_lint_hir_and_then`](diagnostics::span_lint_hir_and_then) +pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl IntoIterator) -> bool { + let mut suppress_lint = false; + + for id in ids { + let (level, _) = cx.tcx.lint_level_at_node(lint, id); + if let Some(expectation) = level.get_expectation_id() { + cx.fulfill_expectation(expectation); + } + + match level { + Level::Allow | Level::Expect(_) => suppress_lint = true, + Level::Warn | Level::ForceWarn(_) | Level::Deny | Level::Forbid => {}, + } + } + + suppress_lint +} + /// Returns `true` if the lint is allowed in the current context. This is useful for /// skipping long running code when it's unnecessary /// @@ -1958,8 +1980,8 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, /// Checks if the given function kind is an async function. pub fn is_async_fn(kind: FnKind<'_>) -> bool { match kind { - FnKind::ItemFn(_, _, header) => header.asyncness == IsAsync::Async, - FnKind::Method(_, sig) => sig.header.asyncness == IsAsync::Async, + FnKind::ItemFn(_, _, header) => header.asyncness.is_async(), + FnKind::Method(_, sig) => sig.header.asyncness.is_async(), FnKind::Closure => false, } } @@ -2049,7 +2071,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool match expr.kind { ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)), - _ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)), + _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)), } } @@ -2429,11 +2451,12 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { }) } -/// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied +/// Checks if `id` has a `#[cfg(test)]` attribute applied /// -/// Note: Add `//@compile-flags: --test` to UI tests with a `#[cfg(test)]` function -pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { - fn is_cfg_test(attr: &Attribute) -> bool { +/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent +/// use [`is_in_cfg_test`] +pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { + tcx.hir().attrs(id).iter().any(|attr| { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() && let [item] = &*items @@ -2443,11 +2466,14 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { } else { false } - } + }) +} + +/// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied +pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { tcx.hir() - .parent_iter(id) - .flat_map(|(parent_id, _)| tcx.hir().attrs(parent_id)) - .any(is_cfg_test) + .parent_id_iter(id) + .any(|parent_id| is_cfg_test(tcx, parent_id)) } /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index 173f9841d4469..eaf590f6ad77d 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -10,8 +10,9 @@ use rustc_lint::LateContext; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol}; -use std::cell::RefCell; +use std::cell::OnceCell; use std::ops::ControlFlow; +use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[ @@ -227,16 +228,26 @@ pub enum PanicExpn<'a> { impl<'a> PanicExpn<'a> { pub fn parse(expr: &'a Expr<'a>) -> Option { - let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else { + let ExprKind::Call(callee, args) = &expr.kind else { return None; }; let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None; }; - let result = match path.segments.last().unwrap().ident.as_str() { + let name = path.segments.last().unwrap().ident.as_str(); + + // This has no argument + if name == "panic_cold_explicit" { + return Some(Self::Empty); + }; + + let [arg, rest @ ..] = args else { + return None; + }; + let result = match name { "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty, "panic" | "panic_str" => Self::Str(arg), - "panic_display" => { + "panic_display" | "panic_cold_display" => { let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None; }; @@ -374,28 +385,21 @@ thread_local! { /// A thread local is used because [`FormatArgs`] is `!Send` and `!Sync`, we are making an /// assumption that the early pass that populates the map and the later late passes will all be /// running on the same thread. - static AST_FORMAT_ARGS: RefCell> = { + #[doc(hidden)] + pub static AST_FORMAT_ARGS: OnceCell>> = { static CALLED: AtomicBool = AtomicBool::new(false); debug_assert!( !CALLED.swap(true, Ordering::SeqCst), "incorrect assumption: `AST_FORMAT_ARGS` should only be accessed by a single thread", ); - RefCell::default() + OnceCell::new() }; } -/// Record [`rustc_ast::FormatArgs`] for use in late lint passes, this should only be called by -/// `FormatArgsCollector` -pub fn collect_ast_format_args(span: Span, format_args: &FormatArgs) { - AST_FORMAT_ARGS.with(|ast_format_args| { - ast_format_args.borrow_mut().insert(span, format_args.clone()); - }); -} - -/// Calls `callback` with an AST [`FormatArgs`] node if a `format_args` expansion is found as a -/// descendant of `expn_id` -pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId, callback: impl FnOnce(&FormatArgs)) { +/// Returns an AST [`FormatArgs`] node if a `format_args` expansion is found as a descendant of +/// `expn_id` +pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option> { let format_args_expr = for_each_expr(start, |expr| { let ctxt = expr.span.ctxt(); if ctxt.outer_expn().is_descendant_of(expn_id) { @@ -410,13 +414,14 @@ pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId, } else { ControlFlow::Continue(Descend::No) } - }); + })?; - if let Some(expr) = format_args_expr { - AST_FORMAT_ARGS.with(|ast_format_args| { - ast_format_args.borrow().get(&expr.span).map(callback); - }); - } + AST_FORMAT_ARGS.with(|ast_format_args| { + ast_format_args + .get()? + .get(&format_args_expr.span.with_parent(None)) + .map(Rc::clone) + }) } /// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 131f3c0aa3946..9dbb4c68d13f8 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -1,7 +1,8 @@ use rustc_hir::{Expr, HirId}; +use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ - traversal, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK, + traversal, BasicBlock, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::TyCtxt; @@ -29,20 +30,26 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - locals.len() ]; - traversal::ReversePostorder::new(mir, location.block).try_fold(init, |usage, (tbb, tdata)| { - // Give up on loops - if tdata.terminator().successors().any(|s| s == location.block) { - return None; - } + traversal::Postorder::new(&mir.basic_blocks, location.block) + .collect::>() + .into_iter() + .rev() + .try_fold(init, |usage, tbb| { + let tdata = &mir.basic_blocks[tbb]; - let mut v = V { - locals, - location, - results: usage, - }; - v.visit_basic_block_data(tbb, tdata); - Some(v.results) - }) + // Give up on loops + if tdata.terminator().successors().any(|s| s == location.block) { + return None; + } + + let mut v = V { + locals, + location, + results: usage, + }; + v.visit_basic_block_data(tbb, tdata); + Some(v.results) + }) } struct V<'a> { @@ -79,8 +86,32 @@ impl<'a, 'tcx> Visitor<'tcx> for V<'a> { } } +/// Checks if the block is part of a cycle +pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool { + let mut seen = BitSet::new_empty(body.basic_blocks.len()); + let mut to_visit = Vec::with_capacity(body.basic_blocks.len() / 2); + + seen.insert(block); + let mut next = block; + loop { + for succ in body.basic_blocks[next].terminator().successors() { + if seen.insert(succ) { + to_visit.push(succ); + } else if succ == block { + return true; + } + } + + if let Some(x) = to_visit.pop() { + next = x; + } else { + return false; + } + } +} + /// Convenience wrapper around `visit_local_usage`. -pub fn used_exactly_once(mir: &rustc_middle::mir::Body<'_>, local: rustc_middle::mir::Local) -> Option { +pub fn used_exactly_once(mir: &Body<'_>, local: rustc_middle::mir::Local) -> Option { visit_local_usage( &[local], mir, @@ -91,11 +122,14 @@ pub fn used_exactly_once(mir: &rustc_middle::mir::Body<'_>, local: rustc_middle: ) .map(|mut vec| { let LocalUsage { local_use_locs, .. } = vec.remove(0); - local_use_locs + let mut locations = local_use_locs .into_iter() - .filter(|location| !is_local_assignment(mir, local, *location)) - .count() - == 1 + .filter(|&location| !is_local_assignment(mir, local, location)); + if let Some(location) = locations.next() { + locations.next().is_none() && !block_in_cycle(mir, location.block) + } else { + false + } }) } diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 0faff05eb2319..df839c2106f14 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -19,7 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { - 1,71,0 { TUPLE_ARRAY_CONVERSIONS } + 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 2fb24b5c7ed9d..1f2bb16f459fc 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -25,17 +25,12 @@ pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", " pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; -pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; -pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; #[cfg(feature = "internal")] pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; #[cfg(feature = "internal")] pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]; -pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "", "EPSILON"]; -pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"]; -pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates @@ -48,8 +43,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; #[cfg(feature = "internal")] pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"]; pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"]; -pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"]; -pub const ITER_ONCE: [&str; 5] = ["core", "iter", "sources", "once", "Once"]; pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; #[cfg(feature = "internal")] pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; @@ -59,10 +52,8 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; #[cfg(feature = "internal")] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; -pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"]; #[cfg(feature = "internal")] pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; -pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; @@ -71,28 +62,9 @@ pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "Rw pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; -pub const PEEKABLE: [&str; 5] = ["core", "iter", "adapters", "peekable", "Peekable"]; -pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"]; #[cfg_attr(not(unix), allow(clippy::invalid_paths))] pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"]; -pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"]; -pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"]; -pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; -pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"]; -pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"]; -pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"]; -pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"]; -pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"]; -pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"]; -pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"]; -pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"]; -pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"]; -pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"]; -pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; -pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; -pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"]; -pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"]; pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"]; pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"]; pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"]; @@ -101,21 +73,11 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"]; pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; -pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; -pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"]; pub const SLICE_GET: [&str; 4] = ["core", "slice", "", "get"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_INTO: [&str; 4] = ["core", "slice", "", "iter"]; -pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; -pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; -pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"]; -pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"]; -pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"]; -pub const STD_IO_LINES: [&str; 3] = ["std", "io", "Lines"]; -pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"]; pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"]; pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"]; -pub const STD_PROCESS_COMMAND: [&str; 3] = ["std", "process", "Command"]; pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"]; pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"]; @@ -136,13 +98,11 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; #[cfg(feature = "internal")] pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; -pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"]; pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"]; -pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"]; @@ -150,18 +110,10 @@ pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"]; pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; -pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; -pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; -pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"]; pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"]; -pub const INSTANT: [&str; 3] = ["std", "time", "Instant"]; pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"]; pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"]; pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"]; pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"]; -pub const FORMATTER: [&str; 3] = ["core", "fmt", "Formatter"]; -pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"]; -pub const ORD_CMP: [&str; 4] = ["core", "cmp", "Ord", "cmp"]; #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so pub const BOOL_THEN: [&str; 4] = ["core", "bool", "", "then"]; -pub const ARRAY_INTO_ITER: [&str; 4] = ["core", "array", "iter", "IntoIter"]; 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 17233058c9c93..55f9cb27ad4db 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 @@ -272,6 +272,7 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B | ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } | ProjectionElem::Deref + | ProjectionElem::Subtype(_) | ProjectionElem::Index(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 9e25d97f5a6bc..2d305a63eca12 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -13,7 +13,8 @@ use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; -use rustc_middle::mir::{ConstValue, interpret::Scalar}; +use rustc_middle::mir::interpret::Scalar; +use rustc_middle::mir::ConstValue; use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ @@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{Obligation, ObligationCause}; use std::assert_matches::debug_assert_matches; use std::iter; -use crate::{match_def_path, path_res, paths}; +use crate::{match_def_path, path_res}; mod type_certainty; pub use type_certainty::expr_type_is_certain; @@ -460,10 +461,8 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { else if is_type_lang_item(cx, ty, LangItem::OwnedBox) || matches!( get_type_diagnostic_name(cx, ty), - Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type) + Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type | sym::RcWeak | sym::ArcWeak) ) - || match_type(cx, ty, &paths::WEAK_RC) - || match_type(cx, ty, &paths::WEAK_ARC) { // Check all of the generic arguments. if let ty::Adt(_, subs) = ty.kind() { diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index dc7756533acb0..7506467232603 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -207,8 +207,8 @@ fn path_segment_certainty( // Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE. if cx.tcx.res_generics_def_id(path_segment.res).is_some() { let generics = cx.tcx.generics_of(def_id); - let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && generics.params.is_empty() - { + let count = generics.params.len() - usize::from(generics.host_effect_index.is_some()); + let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0 { Certainty::Certain(None) } else { Certainty::Uncertain @@ -219,7 +219,7 @@ fn path_segment_certainty( // See the comment preceding `qpath_certainty`. `def_id` could refer to a type or a value. let certainty = lhs.join_clearing_def_ids(rhs); if resolves_to_type { - if let DefKind::TyAlias { .. } = cx.tcx.def_kind(def_id) { + if let DefKind::TyAlias = cx.tcx.def_kind(def_id) { adt_def_id(cx.tcx.type_of(def_id).instantiate_identity()) .map_or(certainty, |def_id| certainty.with_def_id(def_id)) } else { @@ -299,10 +299,11 @@ fn type_is_inferrable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> b // Check that all type parameters appear in the functions input types. (0..(generics.parent_count + generics.params.len()) as u32).all(|index| { - fn_sig - .inputs() - .iter() - .any(|input_ty| contains_param(*input_ty.skip_binder(), index)) + Some(index as usize) == generics.host_effect_index + || fn_sig + .inputs() + .iter() + .any(|input_ty| contains_param(*input_ty.skip_binder(), index)) }) } diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 3b47a451345eb..d752fe7d97ebf 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -62,6 +62,27 @@ where } } } +impl<'tcx, A, B> Visitable<'tcx> for (A, B) +where + A: Visitable<'tcx>, + B: Visitable<'tcx>, +{ + fn visit>(self, visitor: &mut V) { + let (a, b) = self; + a.visit(visitor); + b.visit(visitor); + } +} +impl<'tcx, T> Visitable<'tcx> for Option +where + T: Visitable<'tcx>, +{ + fn visit>(self, visitor: &mut V) { + if let Some(x) = self { + x.visit(visitor); + } + } +} macro_rules! visitable_ref { ($t:ident, $f:ident) => { impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> { @@ -748,3 +769,26 @@ pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool { }) .is_some() } + +/// If the local is only used once in `visitable` returns the path expression referencing the given +/// local +pub fn local_used_once<'tcx>( + cx: &LateContext<'tcx>, + visitable: impl Visitable<'tcx>, + id: HirId, +) -> Option<&'tcx Expr<'tcx>> { + let mut expr = None; + + let cf = for_each_expr_with_closures(cx, visitable, |e| { + if path_to_local_id(e, id) && expr.replace(e).is_some() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }); + if cf.is_some() { + return None; + } + + expr +} diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index 1470da61fac0c..beea9fd00e7a9 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.74" +version = "0.1.75" edition = "2021" publish = false diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 9f5116eb73bb2..fe2c77ab47f00 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-09-07" +channel = "nightly-2023-10-06" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 1d89477dcc16b..d47767faed9ed 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -26,6 +26,8 @@ use std::ops::Deref; use std::path::Path; use std::process::exit; +use anstream::println; + /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. fn arg_value<'a, T: Deref>( @@ -162,39 +164,15 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } } +#[allow(clippy::ignored_unit_patterns)] fn display_help() { - println!( - "\ -Checks a package to catch common mistakes and improve your Rust code. - -Usage: - cargo clippy [options] [--] [...] - -Common options: - -h, --help Print this message - --rustc Pass all args to rustc - -V, --version Print version info and exit - -For the other options see `cargo check --help`. - -To allow or deny a lint from the command line you can use `cargo clippy --` -with: - - -W --warn OPT Set lint warnings - -A --allow OPT Set lint allowed - -D --deny OPT Set lint denied - -F --forbid OPT Set lint forbidden - -You can use tool lints to allow or deny lints from your code, eg.: - - #[allow(clippy::needless_lifetimes)] -" - ); + println!("{}", help_message()); } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; #[allow(clippy::too_many_lines)] +#[allow(clippy::ignored_unit_patterns)] pub fn main() { let handler = EarlyErrorHandler::new(ErrorOutputType::default()); @@ -236,6 +214,7 @@ pub fn main() { if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); + println!("{version_info}"); exit(0); } @@ -292,3 +271,25 @@ pub fn main() { } })) } + +#[must_use] +fn help_message() -> &'static str { + color_print::cstr!( + "Checks a file to catch common mistakes and improve your Rust code. +Run clippy-driver with the same arguments you use for rustc + +Usage: + clippy-driver [OPTIONS] INPUT + +Common options: + -h, --help Print this message + -V, --version Print version info and exit + --rustc Pass all arguments to rustc + +Allowing / Denying lints +You can use tool lints to allow or deny lints from your code, e.g.: + + #[allow(clippy::needless_lifetimes)] +" + ) +} diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index 26b655076cf65..bbf7d22c85043 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -6,37 +6,14 @@ use std::env; use std::path::PathBuf; use std::process::{self, Command}; -const CARGO_CLIPPY_HELP: &str = "Checks a package to catch common mistakes and improve your Rust code. - -Usage: - cargo clippy [options] [--] [...] - -Common options: - --no-deps Run Clippy only on the given crate, without linting the dependencies - --fix Automatically apply lint suggestions. This flag implies `--no-deps` and `--all-targets` - -h, --help Print this message - -V, --version Print version info and exit - --explain LINT Print the documentation for a given lint - -For the other options see `cargo check --help`. - -To allow or deny a lint from the command line you can use `cargo clippy --` -with: - - -W --warn OPT Set lint warnings - -A --allow OPT Set lint allowed - -D --deny OPT Set lint denied - -F --forbid OPT Set lint forbidden - -You can use tool lints to allow or deny lints from your code, e.g.: - - #[allow(clippy::needless_lifetimes)] -"; +use anstream::println; +#[allow(clippy::ignored_unit_patterns)] fn show_help() { - println!("{CARGO_CLIPPY_HELP}"); + println!("{}", help_message()); } +#[allow(clippy::ignored_unit_patterns)] fn show_version() { let version_info = rustc_tools_util::get_version_info!(); println!("{version_info}"); @@ -168,6 +145,38 @@ where } } +#[must_use] +pub fn help_message() -> &'static str { + color_print::cstr!( +"Checks a package to catch common mistakes and improve your Rust code. + +Usage: + cargo clippy [OPTIONS] [--] [<>...] + +Common options: + --no-deps Run Clippy only on the given crate, without linting the dependencies + --fix Automatically apply lint suggestions. This flag implies --no-deps and --all-targets + -h, --help Print this message + -V, --version Print version info and exit + --explain [LINT] Print the documentation for a given lint + +See all options with cargo check --help. + +Allowing / Denying lints + +To allow or deny a lint from the command line you can use cargo clippy -- with: + + -W / --warn [LINT] Set lint warnings + -A / --allow [LINT] Set lint allowed + -D / --deny [LINT] Set lint denied + -F / --forbid [LINT] Set lint forbidden + +You can use tool lints to allow or deny lints from your code, e.g.: + + #[allow(clippy::needless_lifetimes)] +" + ) +} #[cfg(test)] mod tests { use super::ClippyCmd; diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 9fcc269dbf8c2..f340cf5938a7d 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -18,7 +18,6 @@ use test_utils::IS_RUSTC_TEST_SUITE; // in the depinfo file (otherwise cargo thinks they are unused) extern crate clippy_lints; extern crate clippy_utils; -extern crate derive_new; extern crate futures; extern crate if_chain; extern crate itertools; @@ -33,7 +32,6 @@ mod test_utils; static TEST_DEPENDENCIES: &[&str] = &[ "clippy_lints", "clippy_utils", - "derive_new", "futures", "if_chain", "itertools", diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs index b5ff3a5420561..60be297881341 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs @@ -11,6 +11,6 @@ fn main() { const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; - // Don't lint, not yet a diagnostic or language item - const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; + // Don't lint, not a diagnostic or language item + const OPS_MOD: [&str; 5] = ["core", "ops"]; } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr index 58b1fd92b5dc9..076786329cd9f 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr @@ -19,8 +19,8 @@ LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"] error: hardcoded path to a diagnostic item --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43 | -LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const OPS_MOD: [&str; 5] = ["core", "ops"]; + | ^^^^^^^^^^^^^^^ | = help: convert all references to use `sym::deref_method` diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs index fbef5c4564b1b..868cf00a8d469 100644 --- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs +++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs @@ -7,8 +7,10 @@ async fn bad() -> u32 { } async fn bad_reason() -> u32 { - let _x = Ipv4Addr::new(127, 0, 0, 1); - baz().await + let x = Ipv4Addr::new(127, 0, 0, 1); + let y = baz().await; + let _x = x; + y } async fn good() -> u32 { diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr index 6f8b04fd12b94..ddcd1940d475c 100644 --- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr +++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr @@ -11,11 +11,11 @@ LL | let _x = String::from("hello"); error: `std::net::Ipv4Addr` may not be held across an `await` point per `clippy.toml` --> $DIR/await_holding_invalid_type.rs:10:9 | -LL | let _x = Ipv4Addr::new(127, 0, 0, 1); - | ^^ +LL | let x = Ipv4Addr::new(127, 0, 0, 1); + | ^ error: `std::string::String` may not be held across an `await` point per `clippy.toml` - --> $DIR/await_holding_invalid_type.rs:31:13 + --> $DIR/await_holding_invalid_type.rs:33:13 | LL | let _x = String::from("hi!"); | ^^ diff --git a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/clippy.toml b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/clippy.toml new file mode 100644 index 0000000000000..74fc5d249d005 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/clippy.toml @@ -0,0 +1 @@ +literal-representation-threshold = 0xFFFFFF diff --git a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.fixed b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.fixed new file mode 100644 index 0000000000000..750f3be84c040 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.fixed @@ -0,0 +1,6 @@ +#![warn(clippy::decimal_literal_representation)] +fn main() { + let _ = 8388608; + let _ = 0x00FF_FFFF; + //~^ ERROR: integer literal has a better hexadecimal representation +} diff --git a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.rs b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.rs new file mode 100644 index 0000000000000..26b3354d15909 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.rs @@ -0,0 +1,6 @@ +#![warn(clippy::decimal_literal_representation)] +fn main() { + let _ = 8388608; + let _ = 16777215; + //~^ ERROR: integer literal has a better hexadecimal representation +} diff --git a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr new file mode 100644 index 0000000000000..6f817a3fdde42 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr @@ -0,0 +1,11 @@ +error: integer literal has a better hexadecimal representation + --> $DIR/decimal_literal_representation.rs:4:13 + | +LL | let _ = 16777215; + | ^^^^^^^^ help: consider: `0x00FF_FFFF` + | + = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::decimal_literal_representation)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/disallowed_script_idents/clippy.toml b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/clippy.toml new file mode 100644 index 0000000000000..26cb2d77bfd9f --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/clippy.toml @@ -0,0 +1 @@ +allowed-scripts = ["Cyrillic"] diff --git a/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.rs b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.rs new file mode 100644 index 0000000000000..9df1ec6fab0d7 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.rs @@ -0,0 +1,6 @@ +#![warn(clippy::disallowed_script_idents)] +fn main() { + let счётчик = 10; + let カウンタ = 10; + //~^ ERROR: identifier `カウンタ` has a Unicode script that is not allowed by configuration +} diff --git a/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr new file mode 100644 index 0000000000000..31bb5ee3514a5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr @@ -0,0 +1,11 @@ +error: identifier `カウンタ` has a Unicode script that is not allowed by configuration: Katakana + --> $DIR/disallowed_script_idents.rs:4:9 + | +LL | let カウンタ = 10; + | ^^^^^^^^ + | + = note: `-D clippy::disallowed-script-idents` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_script_idents)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml b/src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml new file mode 100644 index 0000000000000..0ad7a97994849 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml @@ -0,0 +1 @@ +enum-variant-name-threshold = 5 diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs new file mode 100644 index 0000000000000..8f4e178ccfe17 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs @@ -0,0 +1,16 @@ +enum Foo { + AFoo, + BFoo, + CFoo, + DFoo, +} +enum Foo2 { + //~^ ERROR: all variants have the same postfix + AFoo, + BFoo, + CFoo, + DFoo, + EFoo, +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr new file mode 100644 index 0000000000000..11039b1db4877 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr @@ -0,0 +1,18 @@ +error: all variants have the same postfix: `Foo` + --> $DIR/enum_variant_names.rs:7:1 + | +LL | / enum Foo2 { +LL | | +LL | | AFoo, +LL | | BFoo, +... | +LL | | EFoo, +LL | | } + | |_^ + | + = help: remove the postfixes and use full paths to the variants instead of glob imports + = note: `-D clippy::enum-variant-names` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::enum_variant_names)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_size/clippy.toml b/src/tools/clippy/tests/ui-toml/enum_variant_size/clippy.toml new file mode 100644 index 0000000000000..64a8017fe02e4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_size/clippy.toml @@ -0,0 +1 @@ +enum-variant-size-threshold = 500 diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.fixed b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.fixed new file mode 100644 index 0000000000000..9ae760ae41aea --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.fixed @@ -0,0 +1,11 @@ +enum Fine { + A(()), + B([u8; 500]), +} +enum Bad { + //~^ ERROR: large size difference between variants + A(()), + B(Box<[u8; 501]>), +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.rs b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.rs new file mode 100644 index 0000000000000..cf7f432bf0b14 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.rs @@ -0,0 +1,11 @@ +enum Fine { + A(()), + B([u8; 500]), +} +enum Bad { + //~^ ERROR: large size difference between variants + A(()), + B([u8; 501]), +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr new file mode 100644 index 0000000000000..4d9bc9d48e45a --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr @@ -0,0 +1,21 @@ +error: large size difference between variants + --> $DIR/enum_variant_size.rs:5:1 + | +LL | / enum Bad { +LL | | +LL | | A(()), + | | ----- the second-largest variant contains at least 0 bytes +LL | | B([u8; 501]), + | | ------------ the largest variant contains at least 501 bytes +LL | | } + | |_^ the entire enum is at least 502 bytes + | + = note: `-D clippy::large-enum-variant` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` +help: consider boxing the large fields to reduce the total size of the enum + | +LL | B(Box<[u8; 501]>), + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml b/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml new file mode 100644 index 0000000000000..f85aade6ae87d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml @@ -0,0 +1 @@ +enum-variant-name-threshold = 0 diff --git a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs b/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs new file mode 100644 index 0000000000000..6918d7528c160 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs @@ -0,0 +1,3 @@ +enum Actions {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/explicit_iter_loop/clippy.toml b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/clippy.toml new file mode 100644 index 0000000000000..15d175ef14785 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/clippy.toml @@ -0,0 +1 @@ +enforce-iter-loop-reborrow = true diff --git a/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.fixed new file mode 100644 index 0000000000000..468da22a926fe --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.fixed @@ -0,0 +1,10 @@ +#![warn(clippy::explicit_iter_loop)] + +fn main() { + let mut vec = vec![1, 2, 3]; + let rmvec = &mut vec; + for _ in &*rmvec {} + //~^ ERROR: it is more concise to loop over references to containers + for _ in &mut *rmvec {} + //~^ ERROR: it is more concise to loop over references to containers +} diff --git a/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.rs b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.rs new file mode 100644 index 0000000000000..a934648608c21 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.rs @@ -0,0 +1,10 @@ +#![warn(clippy::explicit_iter_loop)] + +fn main() { + let mut vec = vec![1, 2, 3]; + let rmvec = &mut vec; + for _ in rmvec.iter() {} + //~^ ERROR: it is more concise to loop over references to containers + for _ in rmvec.iter_mut() {} + //~^ ERROR: it is more concise to loop over references to containers +} diff --git a/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.stderr b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.stderr new file mode 100644 index 0000000000000..587d4f9b3f053 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/explicit_iter_loop/explicit_iter_loop.stderr @@ -0,0 +1,17 @@ +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:6:14 + | +LL | for _ in rmvec.iter() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec` + | + = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::explicit_iter_loop)]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:8:14 + | +LL | for _ in rmvec.iter_mut() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/large_stack_frames/clippy.toml b/src/tools/clippy/tests/ui-toml/large_stack_frames/clippy.toml new file mode 100644 index 0000000000000..584335dc28fb2 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_stack_frames/clippy.toml @@ -0,0 +1 @@ +stack-size-threshold = 1000 diff --git a/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.rs b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.rs new file mode 100644 index 0000000000000..39798ffea4942 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.rs @@ -0,0 +1,17 @@ +#![warn(clippy::large_stack_frames)] + +// We use this helper function instead of writing [0; 4294967297] directly to represent a +// case that large_stack_arrays can't catch +fn create_array() -> [u8; N] { + [0; N] +} + +fn f() { + let _x = create_array::<1000>(); +} +fn f2() { + //~^ ERROR: this function allocates a large amount of stack space + let _x = create_array::<1001>(); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr new file mode 100644 index 0000000000000..67ee57ab672d4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr @@ -0,0 +1,15 @@ +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:12:1 + | +LL | / fn f2() { +LL | | +LL | | let _x = create_array::<1001>(); +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + = note: `-D clippy::large-stack-frames` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/clippy.toml b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/clippy.toml new file mode 100644 index 0000000000000..45bcbce1e3c53 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/clippy.toml @@ -0,0 +1 @@ +pass-by-value-size-limit = 512 diff --git a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.fixed b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.fixed new file mode 100644 index 0000000000000..3c87c79cf2fcc --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.fixed @@ -0,0 +1,7 @@ +#![warn(clippy::large_types_passed_by_value)] + +fn f(_v: [u8; 512]) {} +fn f2(_v: &[u8; 513]) {} +//~^ ERROR: this argument (513 byte) is passed by value + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.rs b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.rs new file mode 100644 index 0000000000000..0572373a61188 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.rs @@ -0,0 +1,7 @@ +#![warn(clippy::large_types_passed_by_value)] + +fn f(_v: [u8; 512]) {} +fn f2(_v: [u8; 513]) {} +//~^ ERROR: this argument (513 byte) is passed by value + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr new file mode 100644 index 0000000000000..6678a2b47214f --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr @@ -0,0 +1,11 @@ +error: this argument (513 byte) is passed by value, but might be more efficient if passed by reference (limit: 512 byte) + --> $DIR/large_types_passed_by_value.rs:4:11 + | +LL | fn f2(_v: [u8; 513]) {} + | ^^^^^^^^^ help: consider passing by reference instead: `&[u8; 513]` + | + = note: `-D clippy::large-types-passed-by-value` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::large_types_passed_by_value)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/manual_let_else/clippy.toml b/src/tools/clippy/tests/ui-toml/manual_let_else/clippy.toml new file mode 100644 index 0000000000000..cdae1da011b0a --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/manual_let_else/clippy.toml @@ -0,0 +1 @@ +matches-for-let-else = "AllTypes" diff --git a/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.fixed b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.fixed new file mode 100644 index 0000000000000..972f6aa40303d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.fixed @@ -0,0 +1,10 @@ +#![warn(clippy::manual_let_else)] + +enum Foo { + A(u8), + B, +} + +fn main() { + let Foo::A(x) = Foo::A(1) else { return }; +} diff --git a/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.rs b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.rs new file mode 100644 index 0000000000000..fdaba4ad2a602 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.rs @@ -0,0 +1,14 @@ +#![warn(clippy::manual_let_else)] + +enum Foo { + A(u8), + B, +} + +fn main() { + let x = match Foo::A(1) { + //~^ ERROR: this could be rewritten as `let...else` + Foo::A(x) => x, + Foo::B => return, + }; +} diff --git a/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr new file mode 100644 index 0000000000000..5c2c86c373189 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr @@ -0,0 +1,15 @@ +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:9:5 + | +LL | / let x = match Foo::A(1) { +LL | | +LL | | Foo::A(x) => x, +LL | | Foo::B => return, +LL | | }; + | |______^ help: consider writing: `let Foo::A(x) = Foo::A(1) else { return };` + | + = note: `-D clippy::manual-let-else` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/path_ends_with_ext/clippy.toml b/src/tools/clippy/tests/ui-toml/path_ends_with_ext/clippy.toml new file mode 100644 index 0000000000000..40d7dfd938ce0 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/path_ends_with_ext/clippy.toml @@ -0,0 +1 @@ +allowed-dotfiles = ["dot"] diff --git a/src/tools/clippy/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs b/src/tools/clippy/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs new file mode 100644 index 0000000000000..a34b15f4ac9ab --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs @@ -0,0 +1,9 @@ +#![warn(clippy::path_ends_with_ext)] + +use std::path::Path; + +fn f(p: &Path) { + p.ends_with(".dot"); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/result_large_err/clippy.toml b/src/tools/clippy/tests/ui-toml/result_large_err/clippy.toml new file mode 100644 index 0000000000000..df505ed9672a6 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/result_large_err/clippy.toml @@ -0,0 +1 @@ +large-error-threshold = 512 diff --git a/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.rs b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.rs new file mode 100644 index 0000000000000..dea4d61a96bfb --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.rs @@ -0,0 +1,10 @@ +#![warn(clippy::result_large_err)] + +fn f() -> Result<(), [u8; 511]> { + todo!() +} +fn f2() -> Result<(), [u8; 512]> { + //~^ ERROR: the `Err`-variant returned from this function is very large + todo!() +} +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr new file mode 100644 index 0000000000000..b0936319d1b9d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr @@ -0,0 +1,12 @@ +error: the `Err`-variant returned from this function is very large + --> $DIR/result_large_err.rs:6:12 + | +LL | fn f2() -> Result<(), [u8; 512]> { + | ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes + | + = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>` + = note: `-D clippy::result-large-err` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::result_large_err)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index b97bb144468b0..4bed5c149f517 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -10,6 +10,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allowed-dotfiles allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed @@ -82,6 +83,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allowed-dotfiles allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.rs b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.rs new file mode 100644 index 0000000000000..2f02361220650 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.rs @@ -0,0 +1,5 @@ +fn f(x: Box<[u8; 500]>) {} +//~^ ERROR: local variable doesn't need to be boxed here +fn f2(x: Box<[u8; 501]>) {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr new file mode 100644 index 0000000000000..2859a29f1b2a2 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr @@ -0,0 +1,11 @@ +error: local variable doesn't need to be boxed here + --> $DIR/boxed_local.rs:1:6 + | +LL | fn f(x: Box<[u8; 500]>) {} + | ^ + | + = note: `-D clippy::boxed-local` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::boxed_local)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/clippy.toml b/src/tools/clippy/tests/ui-toml/too_large_for_stack/clippy.toml new file mode 100644 index 0000000000000..a9c42fca46807 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/clippy.toml @@ -0,0 +1 @@ +too-large-for-stack = 500 diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.fixed b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.fixed new file mode 100644 index 0000000000000..ebe92d9b59946 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.fixed @@ -0,0 +1,9 @@ +#![warn(clippy::useless_vec)] + +fn main() { + let x = [0u8; 500]; + //~^ ERROR: useless use of `vec!` + x.contains(&1); + let y = vec![0u8; 501]; + y.contains(&1); +} diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.rs b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.rs new file mode 100644 index 0000000000000..e2886a8ccd126 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.rs @@ -0,0 +1,9 @@ +#![warn(clippy::useless_vec)] + +fn main() { + let x = vec![0u8; 500]; + //~^ ERROR: useless use of `vec!` + x.contains(&1); + let y = vec![0u8; 501]; + y.contains(&1); +} diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr new file mode 100644 index 0000000000000..923cded5eef18 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr @@ -0,0 +1,11 @@ +error: useless use of `vec!` + --> $DIR/useless_vec.rs:4:13 + | +LL | let x = vec![0u8; 500]; + | ^^^^^^^^^^^^^^ help: you can use an array directly: `[0u8; 500]` + | + = note: `-D clippy::useless-vec` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::useless_vec)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/clippy.toml b/src/tools/clippy/tests/ui-toml/too_many_arguments/clippy.toml new file mode 100644 index 0000000000000..15906305c891b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/clippy.toml @@ -0,0 +1 @@ +too-many-arguments-threshold = 10 diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.rs b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.rs new file mode 100644 index 0000000000000..7b2d6897d3c2c --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.rs @@ -0,0 +1,7 @@ +#![warn(clippy::too_many_arguments)] + +fn not_too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8) {} +fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {} +//~^ ERROR: this function has too many arguments + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr new file mode 100644 index 0000000000000..8b9d159b59c3a --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr @@ -0,0 +1,11 @@ +error: this function has too many arguments (11/10) + --> $DIR/too_many_arguments.rs:4:1 + | +LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::too-many-arguments` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/type_complexity/clippy.toml b/src/tools/clippy/tests/ui-toml/type_complexity/clippy.toml new file mode 100644 index 0000000000000..bf2ffdd0e3071 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_complexity/clippy.toml @@ -0,0 +1 @@ +type-complexity-threshold = 500 diff --git a/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.rs b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.rs new file mode 100644 index 0000000000000..b95f5134347dc --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.rs @@ -0,0 +1,7 @@ +// 480 +fn f(_: (u8, (u8, (u8, (u8, (u8, (u8,))))))) {} +// 550 +fn f2(_: (u8, (u8, (u8, (u8, (u8, (u8, u8))))))) {} +//~^ ERROR: very complex type used + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr new file mode 100644 index 0000000000000..8ca637f722251 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr @@ -0,0 +1,11 @@ +error: very complex type used. Consider factoring parts into `type` definitions + --> $DIR/type_complexity.rs:4:10 + | +LL | fn f2(_: (u8, (u8, (u8, (u8, (u8, (u8, u8))))))) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::type-complexity` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/clippy.toml b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/clippy.toml new file mode 100644 index 0000000000000..2f91866aa9367 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/clippy.toml @@ -0,0 +1 @@ +max-trait-bounds = 5 diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs new file mode 100644 index 0000000000000..2454c10382df7 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs @@ -0,0 +1,18 @@ +#![warn(clippy::type_repetition_in_bounds)] + +fn f() +where + T: Copy + Clone + Sync + Send + ?Sized + Unpin, + T: PartialEq, +{ +} + +fn f2() +where + T: Copy + Clone + Sync + Send + ?Sized, + T: Unpin + PartialEq, + //~^ ERROR: this type has already been used as a bound predicate +{ +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr new file mode 100644 index 0000000000000..2ae2984975f4b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr @@ -0,0 +1,12 @@ +error: this type has already been used as a bound predicate + --> $DIR/main.rs:13:5 + | +LL | T: Unpin + PartialEq, + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider combining the bounds: `T: Copy + Clone + Sync + Send + ?Sized + Unpin + PartialEq` + = note: `-D clippy::type-repetition-in-bounds` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::type_repetition_in_bounds)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml deleted file mode 100644 index e6dbb3d37841b..0000000000000 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml +++ /dev/null @@ -1,2 +0,0 @@ -accept-comment-above-statement = true -accept-comment-above-attributes = true diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/default/clippy.toml b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/default/clippy.toml new file mode 100644 index 0000000000000..3b205d536f2ed --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/default/clippy.toml @@ -0,0 +1,2 @@ +# default configuration has `accept-comment-above-statement` and +# `accept-comment-above-attributes` true diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/disabled/clippy.toml b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/disabled/clippy.toml new file mode 100644 index 0000000000000..57ecb902d6545 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/disabled/clippy.toml @@ -0,0 +1,3 @@ +# test with these options disabled +accept-comment-above-statement = false +accept-comment-above-attributes = false diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr similarity index 83% rename from src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr rename to src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 183c07fe786ce..15edf2a7dae47 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:263:19 + --> $DIR/undocumented_unsafe_blocks.rs:266:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:267:5 + --> $DIR/undocumented_unsafe_blocks.rs:270:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:271:14 + --> $DIR/undocumented_unsafe_blocks.rs:274:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:271:29 + --> $DIR/undocumented_unsafe_blocks.rs:274:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:271:48 + --> $DIR/undocumented_unsafe_blocks.rs:274:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:275:18 + --> $DIR/undocumented_unsafe_blocks.rs:278:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:275:37 + --> $DIR/undocumented_unsafe_blocks.rs:278:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:279:14 + --> $DIR/undocumented_unsafe_blocks.rs:282:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:284:19 + --> $DIR/undocumented_unsafe_blocks.rs:287:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:290:14 + --> $DIR/undocumented_unsafe_blocks.rs:293:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:294:14 + --> $DIR/undocumented_unsafe_blocks.rs:297:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:298:13 + --> $DIR/undocumented_unsafe_blocks.rs:301:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:308:8 + --> $DIR/undocumented_unsafe_blocks.rs:311:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:314:13 + --> $DIR/undocumented_unsafe_blocks.rs:317:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:322:5 + --> $DIR/undocumented_unsafe_blocks.rs:325:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:326:5 + --> $DIR/undocumented_unsafe_blocks.rs:329:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:336:5 + --> $DIR/undocumented_unsafe_blocks.rs:339:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:340:20 + --> $DIR/undocumented_unsafe_blocks.rs:343:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:347:5 + --> $DIR/undocumented_unsafe_blocks.rs:350:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:354:9 + --> $DIR/undocumented_unsafe_blocks.rs:357:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:375:13 + --> $DIR/undocumented_unsafe_blocks.rs:378:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:400:13 + --> $DIR/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:408:5 + --> $DIR/undocumented_unsafe_blocks.rs:411:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:400:13 + --> $DIR/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:414:5 + --> $DIR/undocumented_unsafe_blocks.rs:417:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:460:5 + --> $DIR/undocumented_unsafe_blocks.rs:463:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:464:19 + --> $DIR/undocumented_unsafe_blocks.rs:467:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:468:5 + --> $DIR/undocumented_unsafe_blocks.rs:471:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:472:5 + --> $DIR/undocumented_unsafe_blocks.rs:475:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:471:5 + --> $DIR/undocumented_unsafe_blocks.rs:474:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:473:5 + --> $DIR/undocumented_unsafe_blocks.rs:476:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:480:5 + --> $DIR/undocumented_unsafe_blocks.rs:483:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:489:1 + --> $DIR/undocumented_unsafe_blocks.rs:492:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:502:5 + --> $DIR/undocumented_unsafe_blocks.rs:505:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -291,13 +291,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:501:5 + --> $DIR/undocumented_unsafe_blocks.rs:504:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:503:12 + --> $DIR/undocumented_unsafe_blocks.rs:506:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -305,7 +305,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:506:23 + --> $DIR/undocumented_unsafe_blocks.rs:509:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr similarity index 74% rename from src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr rename to src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 77f6aea2e0d07..cc9530f79b67c 100644 --- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:262:19 + --> $DIR/undocumented_unsafe_blocks.rs:266:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:266:5 + --> $DIR/undocumented_unsafe_blocks.rs:270:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:14 + --> $DIR/undocumented_unsafe_blocks.rs:274:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:29 + --> $DIR/undocumented_unsafe_blocks.rs:274:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:48 + --> $DIR/undocumented_unsafe_blocks.rs:274:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:18 + --> $DIR/undocumented_unsafe_blocks.rs:278:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:37 + --> $DIR/undocumented_unsafe_blocks.rs:278:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:278:14 + --> $DIR/undocumented_unsafe_blocks.rs:282:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:283:19 + --> $DIR/undocumented_unsafe_blocks.rs:287:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:289:14 + --> $DIR/undocumented_unsafe_blocks.rs:293:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:293:14 + --> $DIR/undocumented_unsafe_blocks.rs:297:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:297:13 + --> $DIR/undocumented_unsafe_blocks.rs:301:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:307:8 + --> $DIR/undocumented_unsafe_blocks.rs:311:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:313:13 + --> $DIR/undocumented_unsafe_blocks.rs:317:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:321:5 + --> $DIR/undocumented_unsafe_blocks.rs:325:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:325:5 + --> $DIR/undocumented_unsafe_blocks.rs:329:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:335:5 + --> $DIR/undocumented_unsafe_blocks.rs:339:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:339:20 + --> $DIR/undocumented_unsafe_blocks.rs:343:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:346:5 + --> $DIR/undocumented_unsafe_blocks.rs:350:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:353:9 + --> $DIR/undocumented_unsafe_blocks.rs:357:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:374:13 + --> $DIR/undocumented_unsafe_blocks.rs:378:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:399:13 + --> $DIR/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:407:5 + --> $DIR/undocumented_unsafe_blocks.rs:411:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:399:13 + --> $DIR/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:413:5 + --> $DIR/undocumented_unsafe_blocks.rs:417:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:459:5 + --> $DIR/undocumented_unsafe_blocks.rs:463:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:463:19 + --> $DIR/undocumented_unsafe_blocks.rs:467:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:467:5 + --> $DIR/undocumented_unsafe_blocks.rs:471:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:471:5 + --> $DIR/undocumented_unsafe_blocks.rs:475:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:470:5 + --> $DIR/undocumented_unsafe_blocks.rs:474:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:472:5 + --> $DIR/undocumented_unsafe_blocks.rs:476:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:479:5 + --> $DIR/undocumented_unsafe_blocks.rs:483:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:488:1 + --> $DIR/undocumented_unsafe_blocks.rs:492:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:498:9 + --> $DIR/undocumented_unsafe_blocks.rs:502:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +287,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:501:5 + --> $DIR/undocumented_unsafe_blocks.rs:505:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -299,13 +299,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:500:5 + --> $DIR/undocumented_unsafe_blocks.rs:504:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:502:12 + --> $DIR/undocumented_unsafe_blocks.rs:506:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:505:23 + --> $DIR/undocumented_unsafe_blocks.rs:509:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -321,7 +321,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:523:9 + --> $DIR/undocumented_unsafe_blocks.rs:527:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -329,7 +329,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:527:9 + --> $DIR/undocumented_unsafe_blocks.rs:531:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,12 +337,60 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:531:9 + --> $DIR/undocumented_unsafe_blocks.rs:535:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:541:5 + | +LL | unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:545:5 + | +LL | unsafe { + | ^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:552:9 + | +LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:557:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:563:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a safety comment on the preceding line -error: aborting due to 39 previous errors +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:568:5 + | +LL | unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 45 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index b28e1b7d1802d..a278139876064 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -1,4 +1,7 @@ //@aux-build:../../ui/auxiliary/proc_macro_unsafe.rs +//@revisions: default disabled +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/undocumented_unsafe_blocks/default +//@[disabled] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/undocumented_unsafe_blocks/disabled #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] #![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)] @@ -491,7 +494,7 @@ unsafe impl CrateRoot for () {} // SAFETY: ok unsafe impl CrateRoot for (i32) {} -fn issue_9142() { +fn nested_block_separation_issue_9142() { // SAFETY: ok let _ = // we need this comment to avoid rustfmt putting @@ -518,49 +521,50 @@ pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() - 2 } -fn issue_10832() { - // Safety: A safety comment +fn separate_line_from_let_issue_10832() { + // SAFETY: fail ONLY if `accept-comment-above-statement = false` let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; - // Safety: Another safety comment + // SAFETY: fail ONLY if `accept-comment-above-statement = false` const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; - // Safety: Yet another safety comment + // SAFETY: fail ONLY if `accept-comment-above-statement = false` static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; } -fn issue_8679() { - // SAFETY: +fn above_expr_attribute_issue_8679() { + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] unsafe {} - // SAFETY: + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[expect(unsafe_code, reason = "totally safe")] unsafe { *std::ptr::null::() }; - // Safety: A safety comment + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; - // Safety: Another safety comment + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; - // Safety: Yet another safety comment + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] - static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + #[allow(non_upper_case_globals)] + static _some_static_with_a_very_long_name_to_break_the_line: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; // SAFETY: #[allow(unsafe_code)] - // This also works I guess + // This shouldn't work either unsafe {} } diff --git a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/clippy.toml b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/clippy.toml new file mode 100644 index 0000000000000..7c3ffc2908f3d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/clippy.toml @@ -0,0 +1 @@ +unnecessary-box-size = 64 diff --git a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.fixed b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.fixed new file mode 100644 index 0000000000000..413bc0bf1e378 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.fixed @@ -0,0 +1,11 @@ +#![warn(clippy::unnecessary_box_returns)] + +fn f() -> [u8; 64] { + //~^ ERROR: boxed return of the sized type `[u8; 64]` + todo!() +} +fn f2() -> Box<[u8; 65]> { + todo!() +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.rs b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.rs new file mode 100644 index 0000000000000..b44fbb5544856 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.rs @@ -0,0 +1,11 @@ +#![warn(clippy::unnecessary_box_returns)] + +fn f() -> Box<[u8; 64]> { + //~^ ERROR: boxed return of the sized type `[u8; 64]` + todo!() +} +fn f2() -> Box<[u8; 65]> { + todo!() +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr new file mode 100644 index 0000000000000..df9aa37ac10f4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr @@ -0,0 +1,12 @@ +error: boxed return of the sized type `[u8; 64]` + --> $DIR/unnecessary_box_returns.rs:3:11 + | +LL | fn f() -> Box<[u8; 64]> { + | ^^^^^^^^^^^^^ help: try: `[u8; 64]` + | + = help: changing this also requires a change to the return expressions in this function + = note: `-D clippy::unnecessary-box-returns` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_box_returns)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/clippy.toml b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/clippy.toml new file mode 100644 index 0000000000000..55a202eefb964 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/clippy.toml @@ -0,0 +1 @@ +verbose-bit-mask-threshold = 31 diff --git a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.fixed b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.fixed new file mode 100644 index 0000000000000..437692a4d78c4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.fixed @@ -0,0 +1,7 @@ +#![warn(clippy::verbose_bit_mask)] +fn main() { + let v: i32 = 0; + let _ = v & 0b11111 == 0; + let _ = v.trailing_zeros() >= 6; + //~^ ERROR: bit mask could be simplified +} diff --git a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.rs b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.rs new file mode 100644 index 0000000000000..ce102708055a5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.rs @@ -0,0 +1,7 @@ +#![warn(clippy::verbose_bit_mask)] +fn main() { + let v: i32 = 0; + let _ = v & 0b11111 == 0; + let _ = v & 0b111111 == 0; + //~^ ERROR: bit mask could be simplified +} diff --git a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr new file mode 100644 index 0000000000000..7377921b42ab1 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr @@ -0,0 +1,11 @@ +error: bit mask could be simplified with a call to `trailing_zeros` + --> $DIR/verbose_bit_mask.rs:5:13 + | +LL | let _ = v & 0b111111 == 0; + | ^^^^^^^^^^^^^^^^^ help: try: `v.trailing_zeros() >= 6` + | + = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::verbose_bit_mask)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml b/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml new file mode 100644 index 0000000000000..875aaeef6c935 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml @@ -0,0 +1 @@ +warn-on-all-wildcard-imports = true diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed new file mode 100644 index 0000000000000..1752f48856c2b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed @@ -0,0 +1,11 @@ +#![warn(clippy::wildcard_imports)] + +mod prelude { + pub const FOO: u8 = 1; +} +use prelude::FOO; +//~^ ERROR: usage of wildcard import + +fn main() { + let _ = FOO; +} diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs new file mode 100644 index 0000000000000..331c2c59c222f --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs @@ -0,0 +1,11 @@ +#![warn(clippy::wildcard_imports)] + +mod prelude { + pub const FOO: u8 = 1; +} +use prelude::*; +//~^ ERROR: usage of wildcard import + +fn main() { + let _ = FOO; +} diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr new file mode 100644 index 0000000000000..13ec3a229ce91 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr @@ -0,0 +1,11 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:6:5 + | +LL | use prelude::*; + | ^^^^^^^^^^ help: try: `prelude::FOO` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index 37f0ec2b37d88..79a95d775b11e 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -21,6 +21,18 @@ pub fn derive(_: TokenStream) -> TokenStream { output } +#[proc_macro_derive(ImplStructWithStdDisplay)] +pub fn derive_std(_: TokenStream) -> TokenStream { + quote! { + struct A {} + impl ::std::fmt::Display for A { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "A") + } + } + } +} + #[proc_macro_derive(FieldReassignWithDefault)] pub fn derive_foo(_input: TokenStream) -> TokenStream { quote! { @@ -141,3 +153,19 @@ pub fn shadow_derive(_: TokenStream) -> TokenStream { .into(), ]) } + +#[proc_macro_derive(StructIgnoredUnitPattern)] +pub fn derive_ignored_unit_pattern(_: TokenStream) -> TokenStream { + quote! { + struct A; + impl A { + fn a(&self) -> Result<(), ()> { + unimplemented!() + } + + pub fn b(&self) { + let _ = self.a().unwrap(); + } + } + } +} diff --git a/src/tools/clippy/tests/ui/await_holding_lock.stderr b/src/tools/clippy/tests/ui/await_holding_lock.stderr index 56b111c4d9e41..4782104000228 100644 --- a/src/tools/clippy/tests/ui/await_holding_lock.stderr +++ b/src/tools/clippy/tests/ui/await_holding_lock.stderr @@ -6,13 +6,10 @@ LL | let guard = x.lock().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:9:9 + --> $DIR/await_holding_lock.rs:11:15 | -LL | / let guard = x.lock().unwrap(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ = note: `-D clippy::await-holding-lock` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::await_holding_lock)]` @@ -24,13 +21,10 @@ LL | let guard = x.read().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:25:9 + --> $DIR/await_holding_lock.rs:27:15 | -LL | / let guard = x.read().unwrap(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:31:13 @@ -40,13 +34,10 @@ LL | let mut guard = x.write().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:31:9 + --> $DIR/await_holding_lock.rs:33:15 | -LL | / let mut guard = x.write().unwrap(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:53:13 @@ -56,16 +47,13 @@ LL | let guard = x.lock().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:53:9 - | -LL | / let guard = x.lock().unwrap(); -LL | | -LL | | -LL | | let second = baz().await; -... | -LL | | first + second + third -LL | | } - | |_____^ + --> $DIR/await_holding_lock.rs:56:28 + | +LL | let second = baz().await; + | ^^^^^ +LL | +LL | let third = baz().await; + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:67:17 @@ -75,13 +63,10 @@ LL | let guard = x.lock().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:67:13 + --> $DIR/await_holding_lock.rs:69:19 | -LL | / let guard = x.lock().unwrap(); -LL | | -LL | | baz().await -LL | | }; - | |_________^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:80:17 @@ -91,13 +76,10 @@ LL | let guard = x.lock().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:80:13 + --> $DIR/await_holding_lock.rs:82:19 | -LL | / let guard = x.lock().unwrap(); -LL | | -LL | | baz().await -LL | | } - | |_________^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:93:13 @@ -107,13 +89,10 @@ LL | let guard = x.lock(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:93:9 + --> $DIR/await_holding_lock.rs:95:15 | -LL | / let guard = x.lock(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:109:13 @@ -123,13 +102,10 @@ LL | let guard = x.read(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:109:9 + --> $DIR/await_holding_lock.rs:111:15 | -LL | / let guard = x.read(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:115:13 @@ -139,13 +115,10 @@ LL | let mut guard = x.write(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:115:9 + --> $DIR/await_holding_lock.rs:117:15 | -LL | / let mut guard = x.write(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:137:13 @@ -155,16 +128,13 @@ LL | let guard = x.lock(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:137:9 - | -LL | / let guard = x.lock(); -LL | | -LL | | -LL | | let second = baz().await; -... | -LL | | first + second + third -LL | | } - | |_____^ + --> $DIR/await_holding_lock.rs:140:28 + | +LL | let second = baz().await; + | ^^^^^ +LL | +LL | let third = baz().await; + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:151:17 @@ -174,13 +144,10 @@ LL | let guard = x.lock(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:151:13 + --> $DIR/await_holding_lock.rs:153:19 | -LL | / let guard = x.lock(); -LL | | -LL | | baz().await -LL | | }; - | |_________^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:164:17 @@ -190,13 +157,10 @@ LL | let guard = x.lock(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:164:13 + --> $DIR/await_holding_lock.rs:166:19 | -LL | / let guard = x.lock(); -LL | | -LL | | baz().await -LL | | } - | |_________^ +LL | baz().await + | ^^^^^ error: this `MutexGuard` is held across an `await` point --> $DIR/await_holding_lock.rs:185:9 @@ -206,15 +170,10 @@ LL | let mut guard = x.lock().unwrap(); | = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await note: these are all the `await` points this lock is held through - --> $DIR/await_holding_lock.rs:185:5 - | -LL | / let mut guard = x.lock().unwrap(); -LL | | -LL | | *guard += 1; -LL | | drop(guard); -LL | | baz().await; -LL | | } - | |_^ + --> $DIR/await_holding_lock.rs:189:11 + | +LL | baz().await; + | ^^^^^ error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr index 6b7e1d1afddf4..9264af93dc168 100644 --- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr +++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr @@ -6,13 +6,10 @@ LL | let b = x.borrow(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:6:5 + --> $DIR/await_holding_refcell_ref.rs:8:11 | -LL | / let b = x.borrow(); -LL | | -LL | | baz().await -LL | | } - | |_^ +LL | baz().await + | ^^^^^ = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::await_holding_refcell_ref)]` @@ -24,13 +21,10 @@ LL | let b = x.borrow_mut(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:12:5 + --> $DIR/await_holding_refcell_ref.rs:14:11 | -LL | / let b = x.borrow_mut(); -LL | | -LL | | baz().await -LL | | } - | |_^ +LL | baz().await + | ^^^^^ error: this `RefCell` reference is held across an `await` point --> $DIR/await_holding_refcell_ref.rs:34:9 @@ -40,16 +34,13 @@ LL | let b = x.borrow_mut(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:34:5 - | -LL | / let b = x.borrow_mut(); -LL | | -LL | | -LL | | let second = baz().await; -... | -LL | | first + second + third -LL | | } - | |_^ + --> $DIR/await_holding_refcell_ref.rs:37:24 + | +LL | let second = baz().await; + | ^^^^^ +LL | +LL | let third = baz().await; + | ^^^^^ error: this `RefCell` reference is held across an `await` point --> $DIR/await_holding_refcell_ref.rs:47:9 @@ -59,16 +50,10 @@ LL | let b = x.borrow_mut(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:47:5 - | -LL | / let b = x.borrow_mut(); -LL | | -LL | | -LL | | let second = baz().await; -... | -LL | | first + second + third -LL | | } - | |_^ + --> $DIR/await_holding_refcell_ref.rs:50:24 + | +LL | let second = baz().await; + | ^^^^^ error: this `RefCell` reference is held across an `await` point --> $DIR/await_holding_refcell_ref.rs:63:13 @@ -78,13 +63,10 @@ LL | let b = x.borrow_mut(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:63:9 + --> $DIR/await_holding_refcell_ref.rs:65:15 | -LL | / let b = x.borrow_mut(); -LL | | -LL | | baz().await -LL | | }; - | |_____^ +LL | baz().await + | ^^^^^ error: this `RefCell` reference is held across an `await` point --> $DIR/await_holding_refcell_ref.rs:76:13 @@ -94,13 +76,10 @@ LL | let b = x.borrow_mut(); | = help: ensure the reference is dropped before calling `await` note: these are all the `await` points this reference is held through - --> $DIR/await_holding_refcell_ref.rs:76:9 + --> $DIR/await_holding_refcell_ref.rs:78:15 | -LL | / let b = x.borrow_mut(); -LL | | -LL | | baz().await -LL | | } - | |_____^ +LL | baz().await + | ^^^^^ error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed index 22c034c88ab1c..69cabcb32d333 100644 --- a/src/tools/clippy/tests/ui/box_default.fixed +++ b/src/tools/clippy/tests/ui/box_default.fixed @@ -36,7 +36,7 @@ fn main() { issue_10381(); // `Box::>::default()` would be valid here, but not `Box::default()` or - // `Box::::default()` + // `Box::::default()` // // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563 let mut unnameable = Box::new(Option::default()); diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs index 89e3888ba211a..48fa8bc33bc2d 100644 --- a/src/tools/clippy/tests/ui/box_default.rs +++ b/src/tools/clippy/tests/ui/box_default.rs @@ -36,7 +36,7 @@ fn main() { issue_10381(); // `Box::>::default()` would be valid here, but not `Box::default()` or - // `Box::::default()` + // `Box::::default()` // // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563 let mut unnameable = Box::new(Option::default()); diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index d0a092093f3e0..1ca18170f8a0e 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -361,3 +361,7 @@ fn avoid_subtract_overflow(q: u32) { //~^ ERROR: casting `u32` to `u8` may truncate the value c as usize; } + +fn issue11426() { + (&42u8 >> 0xa9008fb6c9d81e42_0e25730562a601c8_u128) as usize; +} diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed index 6547107f50060..5e7e545e764a5 100644 --- a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed +++ b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed @@ -49,3 +49,14 @@ mod cast_lossless_in_impl { enum Test { A = u32::MAX as i64 + 1, } + +fn issue11458() { + macro_rules! sign_cast { + ($var: ident, $src: ty, $dest: ty) => { + <$dest>::from_ne_bytes(($var as $src).to_ne_bytes()) + }; + } + let x = 10_u128; + let _ = i32::from(sign_cast!(x, u8, i8)); + let _ = i32::from(sign_cast!(x, u8, i8) + 1); +} diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.rs b/src/tools/clippy/tests/ui/cast_lossless_integer.rs index 79af9a83ca286..0d69ddbd586a5 100644 --- a/src/tools/clippy/tests/ui/cast_lossless_integer.rs +++ b/src/tools/clippy/tests/ui/cast_lossless_integer.rs @@ -49,3 +49,14 @@ mod cast_lossless_in_impl { enum Test { A = u32::MAX as i64 + 1, } + +fn issue11458() { + macro_rules! sign_cast { + ($var: ident, $src: ty, $dest: ty) => { + <$dest>::from_ne_bytes(($var as $src).to_ne_bytes()) + }; + } + let x = 10_u128; + let _ = sign_cast!(x, u8, i8) as i32; + let _ = (sign_cast!(x, u8, i8) + 1) as i32; +} diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr index da75cb195ebae..f9f111a7c20f1 100644 --- a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr +++ b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr @@ -115,5 +115,17 @@ error: casting `u8` to `u16` may become silently lossy if you later change the t LL | let _ = (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` -error: aborting due to 19 previous errors +error: casting `i8` to `i32` may become silently lossy if you later change the type + --> $DIR/cast_lossless_integer.rs:60:13 + | +LL | let _ = sign_cast!(x, u8, i8) as i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))` + +error: casting `i8` to `i32` may become silently lossy if you later change the type + --> $DIR/cast_lossless_integer.rs:61:13 + | +LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)` + +error: aborting due to 21 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr index fc5347c86cdeb..7fc62d4fcf855 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr @@ -1,8 +1,8 @@ warning: future cannot be sent between threads safely - --> $DIR/ice-10645.rs:5:35 + --> $DIR/ice-10645.rs:5:1 | LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^ future returned by `bar` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `bar` is not `Send` | note: captured value is not `Send` --> $DIR/ice-10645.rs:5:29 diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr index 68a5766c90c0e..11081dc8087e2 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr @@ -27,7 +27,7 @@ LL | fn bug() -> impl Iterator { | ^^^^^^^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]` + found closure `{closure@$DIR/ice-6251.rs:4:44: 4:53}` error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index cb65360d1291c..f929bec9583c5 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -31,7 +31,7 @@ LL | const VAL: T; | ------------ `VAL` from trait ... LL | impl TypeVal for Multiply where N: TypeVal {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed index f1cac8c5fbc63..32c7499bf73f6 100644 --- a/src/tools/clippy/tests/ui/eta.fixed +++ b/src/tools/clippy/tests/ui/eta.fixed @@ -7,7 +7,8 @@ clippy::option_map_unit_fn, clippy::redundant_closure_call, clippy::uninlined_format_args, - clippy::useless_vec + clippy::useless_vec, + clippy::unnecessary_map_on_constructor )] use std::path::{Path, PathBuf}; diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs index c7a470b5be6df..25b7431ba8cd7 100644 --- a/src/tools/clippy/tests/ui/eta.rs +++ b/src/tools/clippy/tests/ui/eta.rs @@ -7,7 +7,8 @@ clippy::option_map_unit_fn, clippy::redundant_closure_call, clippy::uninlined_format_args, - clippy::useless_vec + clippy::useless_vec, + clippy::unnecessary_map_on_constructor )] use std::path::{Path, PathBuf}; diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr index 7c7f179746205..951e4ac749c25 100644 --- a/src/tools/clippy/tests/ui/eta.stderr +++ b/src/tools/clippy/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:28:27 + --> $DIR/eta.rs:29:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -8,31 +8,31 @@ LL | let a = Some(1u8).map(|a| foo(a)); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` error: redundant closure - --> $DIR/eta.rs:32:40 + --> $DIR/eta.rs:33:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:33:35 + --> $DIR/eta.rs:34:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: redundant closure - --> $DIR/eta.rs:34:26 + --> $DIR/eta.rs:35:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:41:27 + --> $DIR/eta.rs:42:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:93:51 + --> $DIR/eta.rs:94:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -41,127 +41,127 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]` error: redundant closure - --> $DIR/eta.rs:94:51 + --> $DIR/eta.rs:95:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:96:42 + --> $DIR/eta.rs:97:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:100:29 + --> $DIR/eta.rs:101:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:101:27 + --> $DIR/eta.rs:102:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:103:65 + --> $DIR/eta.rs:104:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:166:22 + --> $DIR/eta.rs:167:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:173:27 + --> $DIR/eta.rs:174:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:178:27 + --> $DIR/eta.rs:179:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:210:28 + --> $DIR/eta.rs:211:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:211:28 + --> $DIR/eta.rs:212:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:212:28 + --> $DIR/eta.rs:213:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:219:21 + --> $DIR/eta.rs:220:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:223:21 + --> $DIR/eta.rs:224:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> $DIR/eta.rs:316:18 + --> $DIR/eta.rs:317:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:319:19 + --> $DIR/eta.rs:320:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:323:26 + --> $DIR/eta.rs:324:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> $DIR/eta.rs:335:19 + --> $DIR/eta.rs:336:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> $DIR/eta.rs:338:19 + --> $DIR/eta.rs:339:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> $DIR/eta.rs:341:17 + --> $DIR/eta.rs:342:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> $DIR/eta.rs:345:17 + --> $DIR/eta.rs:346:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` error: redundant closure - --> $DIR/eta.rs:388:19 + --> $DIR/eta.rs:389:19 | LL | let _ = f(&0, |x, y| f2(x, y)); | ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2` diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed index a4943344a11ef..c9bebabdf17ae 100644 --- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed +++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed @@ -113,4 +113,19 @@ with_span!( } ); +mod issue11302 { + use std::fmt::Debug; + use std::marker::PhantomData; + + #[derive(Debug)] + struct Wrapper(PhantomData); + + fn store(v: &mut Vec>) + where + Wrapper: Debug, + { + v.push(Box::new(Wrapper(PhantomData))); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs index 6d85b1ce9d4f3..1bc0047adf01f 100644 --- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs +++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs @@ -113,4 +113,19 @@ with_span!( } ); +mod issue11302 { + use std::fmt::Debug; + use std::marker::PhantomData; + + #[derive(Debug)] + struct Wrapper(PhantomData); + + fn store(v: &mut Vec>) + where + Wrapper: Debug, + { + v.push(Box::new(Wrapper(PhantomData))); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.fixed b/src/tools/clippy/tests/ui/filter_map_bool_then.fixed index 6de870a928985..6a1b81fdbcbe8 100644 --- a/src/tools/clippy/tests/ui/filter_map_bool_then.fixed +++ b/src/tools/clippy/tests/ui/filter_map_bool_then.fixed @@ -55,3 +55,27 @@ fn main() { fn issue11309<'a>(iter: impl Iterator) -> Vec<&'a str> { iter.filter_map(|(_, s): (&str, _)| Some(s)).collect() } + +fn issue11503() { + let bools: &[bool] = &[true, false, false, true]; + let _: Vec = bools.iter().enumerate().filter(|&(i, b)| *b).map(|(i, b)| i).collect(); + + // Need to insert multiple derefs if there is more than one layer of references + let bools: &[&&bool] = &[&&true, &&false, &&false, &&true]; + let _: Vec = bools.iter().enumerate().filter(|&(i, b)| ***b).map(|(i, b)| i).collect(); + + // Should also suggest derefs when going through a mutable reference + let bools: &[&mut bool] = &[&mut true]; + let _: Vec = bools.iter().enumerate().filter(|&(i, b)| **b).map(|(i, b)| i).collect(); + + // Should also suggest derefs when going through a custom deref + struct DerefToBool; + impl std::ops::Deref for DerefToBool { + type Target = bool; + fn deref(&self) -> &Self::Target { + &true + } + } + let bools: &[&&DerefToBool] = &[&&DerefToBool]; + let _: Vec = bools.iter().enumerate().filter(|&(i, b)| ****b).map(|(i, b)| i).collect(); +} diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.rs b/src/tools/clippy/tests/ui/filter_map_bool_then.rs index 4108177e3a0e3..a41e88f8805de 100644 --- a/src/tools/clippy/tests/ui/filter_map_bool_then.rs +++ b/src/tools/clippy/tests/ui/filter_map_bool_then.rs @@ -55,3 +55,27 @@ fn main() { fn issue11309<'a>(iter: impl Iterator) -> Vec<&'a str> { iter.filter_map(|(_, s): (&str, _)| Some(s)).collect() } + +fn issue11503() { + let bools: &[bool] = &[true, false, false, true]; + let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + + // Need to insert multiple derefs if there is more than one layer of references + let bools: &[&&bool] = &[&&true, &&false, &&false, &&true]; + let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + + // Should also suggest derefs when going through a mutable reference + let bools: &[&mut bool] = &[&mut true]; + let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + + // Should also suggest derefs when going through a custom deref + struct DerefToBool; + impl std::ops::Deref for DerefToBool { + type Target = bool; + fn deref(&self) -> &Self::Target { + &true + } + } + let bools: &[&&DerefToBool] = &[&&DerefToBool]; + let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); +} diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.stderr b/src/tools/clippy/tests/ui/filter_map_bool_then.stderr index 86ef6edf8eeda..fab6987913a10 100644 --- a/src/tools/clippy/tests/ui/filter_map_bool_then.stderr +++ b/src/tools/clippy/tests/ui/filter_map_bool_then.stderr @@ -37,5 +37,29 @@ error: usage of `bool::then` in `filter_map` LL | v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i == &NonCopy)).map(|i| i)` -error: aborting due to 6 previous errors +error: usage of `bool::then` in `filter_map` + --> $DIR/filter_map_bool_then.rs:61:50 + | +LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| *b).map(|(i, b)| i)` + +error: usage of `bool::then` in `filter_map` + --> $DIR/filter_map_bool_then.rs:65:50 + | +LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| ***b).map(|(i, b)| i)` + +error: usage of `bool::then` in `filter_map` + --> $DIR/filter_map_bool_then.rs:69:50 + | +LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| **b).map(|(i, b)| i)` + +error: usage of `bool::then` in `filter_map` + --> $DIR/filter_map_bool_then.rs:80:50 + | +LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| ****b).map(|(i, b)| i)` + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr index 371ea1612601e..4b06cd0388990 100644 --- a/src/tools/clippy/tests/ui/functions.stderr +++ b/src/tools/clippy/tests/ui/functions.stderr @@ -2,7 +2,7 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:8:1 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` @@ -17,7 +17,7 @@ LL | | two: u32, ... | LL | | eight: () LL | | ) { - | |__^ + | |_^ error: this function has too many arguments (8/7) --> $DIR/functions.rs:48:5 @@ -29,7 +29,7 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:58:5 | LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:68:34 diff --git a/src/tools/clippy/tests/ui/future_not_send.rs b/src/tools/clippy/tests/ui/future_not_send.rs index 06090e2713dee..9274340b5caa5 100644 --- a/src/tools/clippy/tests/ui/future_not_send.rs +++ b/src/tools/clippy/tests/ui/future_not_send.rs @@ -59,6 +59,7 @@ where { let rt = &t; async { true }.await; + let _ = rt; t } diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr index e417de723ff3e..7ef4947f1d6c5 100644 --- a/src/tools/clippy/tests/ui/future_not_send.stderr +++ b/src/tools/clippy/tests/ui/future_not_send.stderr @@ -1,8 +1,8 @@ error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:7:62 + --> $DIR/future_not_send.rs:7:1 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { - | ^^^^ future returned by `private_future` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await --> $DIR/future_not_send.rs:9:20 @@ -12,28 +12,21 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { LL | LL | async { true }.await | ^^^^^ await occurs here, with `rc` maybe used later -LL | } - | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` -note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:9:20 +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + --> $DIR/future_not_send.rs:7:39 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { - | ---- has type `&std::cell::Cell` which is not `Send` -LL | -LL | async { true }.await - | ^^^^^ await occurs here, with `cell` maybe used later -LL | } - | - `cell` is later dropped here + | ^^^^ has type `&std::cell::Cell` which is not `Send`, because `std::cell::Cell` is not `Sync` = note: `std::cell::Cell` doesn't implement `std::marker::Sync` = note: `-D clippy::future-not-send` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:12:42 + --> $DIR/future_not_send.rs:12:1 | LL | pub async fn public_future(rc: Rc<[u8]>) { - | ^ future returned by `public_future` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await --> $DIR/future_not_send.rs:14:20 @@ -43,15 +36,13 @@ LL | pub async fn public_future(rc: Rc<[u8]>) { LL | LL | async { true }.await; | ^^^^^ await occurs here, with `rc` maybe used later -LL | } - | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:21:63 + --> $DIR/future_not_send.rs:21:1 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { - | ^^^^ future returned by `private_future2` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send` | note: captured value is not `Send` --> $DIR/future_not_send.rs:21:26 @@ -67,10 +58,10 @@ LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { = note: `std::cell::Cell` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:26:43 + --> $DIR/future_not_send.rs:26:1 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} - | ^ future returned by `public_future2` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send` | note: captured value is not `Send` --> $DIR/future_not_send.rs:26:29 @@ -80,10 +71,10 @@ LL | pub async fn public_future2(rc: Rc<[u8]>) {} = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:38:39 + --> $DIR/future_not_send.rs:38:5 | LL | async fn private_future(&self) -> usize { - | ^^^^^ future returned by `private_future` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await --> $DIR/future_not_send.rs:40:24 @@ -93,34 +84,29 @@ LL | async fn private_future(&self) -> usize { LL | LL | async { true }.await; | ^^^^^ await occurs here, with `&self` maybe used later -LL | self.rc.len() -LL | } - | - `&self` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:44:39 + --> $DIR/future_not_send.rs:44:5 | LL | pub async fn public_future(&self) { - | ^ future returned by `public_future` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | -note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:46:31 +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + --> $DIR/future_not_send.rs:44:32 | LL | pub async fn public_future(&self) { - | ----- has type `&Dummy` which is not `Send` -LL | -LL | self.private_future().await; - | ^^^^^ await occurs here, with `&self` maybe used later -LL | } - | - `&self` is later dropped here + | ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:55:37 + --> $DIR/future_not_send.rs:55:1 | -LL | async fn generic_future(t: T) -> T - | ^ future returned by `generic_future` is not `Send` +LL | / async fn generic_future(t: T) -> T +LL | | +LL | | where +LL | | T: Send, + | |____________^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await --> $DIR/future_not_send.rs:61:20 @@ -129,19 +115,16 @@ LL | let rt = &t; | -- has type `&T` which is not `Send` LL | async { true }.await; | ^^^^^ await occurs here, with `rt` maybe used later -LL | t -LL | } - | - `rt` is later dropped here = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:72:34 + --> $DIR/future_not_send.rs:73:1 | LL | async fn unclear_future(t: T) {} - | ^ future returned by `unclear_future` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `unclear_future` is not `Send` | note: captured value is not `Send` - --> $DIR/future_not_send.rs:72:28 + --> $DIR/future_not_send.rs:73:28 | LL | async fn unclear_future(t: T) {} | ^ has type `T` which is not `Send` diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed index 6c6f21fee16b0..15eaf1f659abf 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed @@ -1,3 +1,4 @@ +//@aux-build:proc_macro_derive.rs #![warn(clippy::ignored_unit_patterns)] #![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)] @@ -14,8 +15,22 @@ fn main() { //~^ ERROR: matching over `()` is more explicit let _ = foo().map_err(|()| todo!()); //~^ ERROR: matching over `()` is more explicit + + println!( + "{:?}", + match foo() { + Ok(()) => {}, + //~^ ERROR: matching over `()` is more explicit + Err(()) => {}, + //~^ ERROR: matching over `()` is more explicit + } + ); } +// ignored_unit_patterns in derive macro should be ok +#[derive(proc_macro_derive::StructIgnoredUnitPattern)] +pub struct B; + #[allow(unused)] pub fn moo(_: ()) { let () = foo().unwrap(); diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs index 5e8c2e03ba2cb..9cac3a440aba3 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs @@ -1,3 +1,4 @@ +//@aux-build:proc_macro_derive.rs #![warn(clippy::ignored_unit_patterns)] #![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)] @@ -14,8 +15,22 @@ fn main() { //~^ ERROR: matching over `()` is more explicit let _ = foo().map_err(|_| todo!()); //~^ ERROR: matching over `()` is more explicit + + println!( + "{:?}", + match foo() { + Ok(_) => {}, + //~^ ERROR: matching over `()` is more explicit + Err(_) => {}, + //~^ ERROR: matching over `()` is more explicit + } + ); } +// ignored_unit_patterns in derive macro should be ok +#[derive(proc_macro_derive::StructIgnoredUnitPattern)] +pub struct B; + #[allow(unused)] pub fn moo(_: ()) { let _ = foo().unwrap(); diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr index df5e1d89e906e..cac01a87dba0d 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr @@ -1,5 +1,5 @@ error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:10:12 + --> $DIR/ignored_unit_patterns.rs:11:12 | LL | Ok(_) => {}, | ^ help: use `()` instead of `_`: `()` @@ -8,28 +8,40 @@ LL | Ok(_) => {}, = help: to override `-D warnings` add `#[allow(clippy::ignored_unit_patterns)]` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:11:13 + --> $DIR/ignored_unit_patterns.rs:12:13 | LL | Err(_) => {}, | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:13:15 + --> $DIR/ignored_unit_patterns.rs:14:15 | LL | if let Ok(_) = foo() {} | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:15:28 + --> $DIR/ignored_unit_patterns.rs:16:28 | LL | let _ = foo().map_err(|_| todo!()); | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:21:9 + --> $DIR/ignored_unit_patterns.rs:22:16 + | +LL | Ok(_) => {}, + | ^ help: use `()` instead of `_`: `()` + +error: matching over `()` is more explicit + --> $DIR/ignored_unit_patterns.rs:24:17 + | +LL | Err(_) => {}, + | ^ help: use `()` instead of `_`: `()` + +error: matching over `()` is more explicit + --> $DIR/ignored_unit_patterns.rs:36:9 | LL | let _ = foo().unwrap(); | ^ help: use `()` instead of `_`: `()` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/infinite_loop.rs b/src/tools/clippy/tests/ui/infinite_loop.rs index 281e12c7b938a..765c670114746 100644 --- a/src/tools/clippy/tests/ui/infinite_loop.rs +++ b/src/tools/clippy/tests/ui/infinite_loop.rs @@ -7,8 +7,6 @@ fn fn_constref(i: &i32) -> i32 { unimplemented!() } fn fn_mutref(i: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably - //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` unimplemented!() } fn fooi() -> i32 { diff --git a/src/tools/clippy/tests/ui/infinite_loop.stderr b/src/tools/clippy/tests/ui/infinite_loop.stderr index c32b5e323c09e..a78e47d02290c 100644 --- a/src/tools/clippy/tests/ui/infinite_loop.stderr +++ b/src/tools/clippy/tests/ui/infinite_loop.stderr @@ -1,5 +1,5 @@ error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:24:11 + --> $DIR/infinite_loop.rs:22:11 | LL | while y < 10 { | ^^^^^^ @@ -8,7 +8,7 @@ LL | while y < 10 { = note: `#[deny(clippy::while_immutable_condition)]` on by default error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:31:11 + --> $DIR/infinite_loop.rs:29:11 | LL | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | while y < 10 && x < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:40:11 + --> $DIR/infinite_loop.rs:38:11 | LL | while !cond { | ^^^^^ @@ -24,7 +24,7 @@ LL | while !cond { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:86:11 + --> $DIR/infinite_loop.rs:84:11 | LL | while i < 3 { | ^^^^^ @@ -32,7 +32,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:93:11 + --> $DIR/infinite_loop.rs:91:11 | LL | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | while i < 3 && j > 0 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:99:11 + --> $DIR/infinite_loop.rs:97:11 | LL | while i < 3 { | ^^^^^ @@ -48,7 +48,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:116:11 + --> $DIR/infinite_loop.rs:114:11 | LL | while i < 3 { | ^^^^^ @@ -56,7 +56,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:123:11 + --> $DIR/infinite_loop.rs:121:11 | LL | while i < 3 { | ^^^^^ @@ -64,7 +64,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:191:15 + --> $DIR/infinite_loop.rs:189:15 | LL | while self.count < n { | ^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | while self.count < n { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:201:11 + --> $DIR/infinite_loop.rs:199:11 | LL | while y < 10 { | ^^^^^^ @@ -82,7 +82,7 @@ LL | while y < 10 { = help: rewrite it as `if cond { loop { } }` error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:210:11 + --> $DIR/infinite_loop.rs:208:11 | LL | while y < 10 { | ^^^^^^ @@ -91,14 +91,5 @@ LL | while y < 10 { = note: this loop contains `return`s or `break`s = help: rewrite it as `if cond { loop { } }` -error: this argument is a mutable reference, but not used mutably - --> $DIR/infinite_loop.rs:9:17 - | -LL | fn fn_mutref(i: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.rs b/src/tools/clippy/tests/ui/into_iter_without_iter.rs new file mode 100644 index 0000000000000..6be3bb8abdddc --- /dev/null +++ b/src/tools/clippy/tests/ui/into_iter_without_iter.rs @@ -0,0 +1,124 @@ +//@no-rustfix +#![warn(clippy::into_iter_without_iter)] + +use std::iter::IntoIterator; + +fn main() { + { + struct S; + + impl<'a> IntoIterator for &'a S { + //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method + type IntoIter = std::slice::Iter<'a, u8>; + type Item = &'a u8; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + impl<'a> IntoIterator for &'a mut S { + //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + type IntoIter = std::slice::IterMut<'a, u8>; + type Item = &'a mut u8; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } + { + struct S(T); + impl<'a, T> IntoIterator for &'a S { + //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method + type IntoIter = std::slice::Iter<'a, T>; + type Item = &'a T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + impl<'a, T> IntoIterator for &'a mut S { + //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + type IntoIter = std::slice::IterMut<'a, T>; + type Item = &'a mut T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } + { + // Both iter and iter_mut methods exist, don't lint + struct S<'a, T>(&'a T); + + impl<'a, T> S<'a, T> { + fn iter(&self) -> std::slice::Iter<'a, T> { + todo!() + } + fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> { + todo!() + } + } + + impl<'a, T> IntoIterator for &S<'a, T> { + type IntoIter = std::slice::Iter<'a, T>; + type Item = &'a T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + + impl<'a, T> IntoIterator for &mut S<'a, T> { + type IntoIter = std::slice::IterMut<'a, T>; + type Item = &'a mut T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } + { + // Only `iter` exists, no `iter_mut` + struct S<'a, T>(&'a T); + + impl<'a, T> S<'a, T> { + fn iter(&self) -> std::slice::Iter<'a, T> { + todo!() + } + } + + impl<'a, T> IntoIterator for &S<'a, T> { + type IntoIter = std::slice::Iter<'a, T>; + type Item = &'a T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + + impl<'a, T> IntoIterator for &mut S<'a, T> { + //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + type IntoIter = std::slice::IterMut<'a, T>; + type Item = &'a mut T; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } + { + // `iter` exists, but `IntoIterator` is implemented for an alias. inherent_impls doesn't "normalize" + // aliases so that `inherent_impls(Alias)` where `type Alias = S` returns nothing, so this can lead + // to fun FPs. Make sure it doesn't happen here (we're using type_of, which should skip the alias). + struct S; + + impl S { + fn iter(&self) -> std::slice::Iter<'static, u8> { + todo!() + } + } + + type Alias = S; + + impl IntoIterator for &Alias { + type IntoIter = std::slice::Iter<'static, u8>; + type Item = &'static u8; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } +} diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr new file mode 100644 index 0000000000000..f543d1d8e86c1 --- /dev/null +++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr @@ -0,0 +1,114 @@ +error: `IntoIterator` implemented for a reference type without an `iter` method + --> $DIR/into_iter_without_iter.rs:10:9 + | +LL | / impl<'a> IntoIterator for &'a S { +LL | | +LL | | type IntoIter = std::slice::Iter<'a, u8>; +LL | | type Item = &'a u8; +... | +LL | | } +LL | | } + | |_________^ + | + = note: `-D clippy::into-iter-without-iter` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::into_iter_without_iter)]` +help: consider implementing `iter` + | +LL ~ +LL + impl S { +LL + fn iter(&self) -> std::slice::Iter<'a, u8> { +LL + <&Self as IntoIterator>::into_iter(self) +LL + } +LL + } + | + +error: `IntoIterator` implemented for a reference type without an `iter_mut` method + --> $DIR/into_iter_without_iter.rs:18:9 + | +LL | / impl<'a> IntoIterator for &'a mut S { +LL | | +LL | | type IntoIter = std::slice::IterMut<'a, u8>; +LL | | type Item = &'a mut u8; +... | +LL | | } +LL | | } + | |_________^ + | +help: consider implementing `iter_mut` + | +LL ~ +LL + impl S { +LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, u8> { +LL + <&mut Self as IntoIterator>::into_iter(self) +LL + } +LL + } + | + +error: `IntoIterator` implemented for a reference type without an `iter` method + --> $DIR/into_iter_without_iter.rs:29:9 + | +LL | / impl<'a, T> IntoIterator for &'a S { +LL | | +LL | | type IntoIter = std::slice::Iter<'a, T>; +LL | | type Item = &'a T; +... | +LL | | } +LL | | } + | |_________^ + | +help: consider implementing `iter` + | +LL ~ +LL + impl S { +LL + fn iter(&self) -> std::slice::Iter<'a, T> { +LL + <&Self as IntoIterator>::into_iter(self) +LL + } +LL + } + | + +error: `IntoIterator` implemented for a reference type without an `iter_mut` method + --> $DIR/into_iter_without_iter.rs:37:9 + | +LL | / impl<'a, T> IntoIterator for &'a mut S { +LL | | +LL | | type IntoIter = std::slice::IterMut<'a, T>; +LL | | type Item = &'a mut T; +... | +LL | | } +LL | | } + | |_________^ + | +help: consider implementing `iter_mut` + | +LL ~ +LL + impl S { +LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> { +LL + <&mut Self as IntoIterator>::into_iter(self) +LL + } +LL + } + | + +error: `IntoIterator` implemented for a reference type without an `iter_mut` method + --> $DIR/into_iter_without_iter.rs:93:9 + | +LL | / impl<'a, T> IntoIterator for &mut S<'a, T> { +LL | | +LL | | type IntoIter = std::slice::IterMut<'a, T>; +LL | | type Item = &'a mut T; +... | +LL | | } +LL | | } + | |_________^ + | +help: consider implementing `iter_mut` + | +LL ~ +LL + impl S<'a, T> { +LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> { +LL + <&mut Self as IntoIterator>::into_iter(self) +LL + } +LL + } + | + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs b/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs new file mode 100644 index 0000000000000..d9c0aef88c8cf --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs @@ -0,0 +1,11 @@ +//@aux-build:../auxiliary/proc_macros.rs +extern crate proc_macros; + +proc_macros::with_span! { + span + #[cfg(test)] + mod tests {} +} + +#[test] +fn f() {} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs new file mode 100644 index 0000000000000..69d61790121c0 --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs @@ -0,0 +1,4 @@ +#[cfg(test)] +mod tests {} + +fn in_submodule() {} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr deleted file mode 100644 index 1b6257471618c..0000000000000 --- a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: Option 'test' given more than once - diff --git a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs new file mode 100644 index 0000000000000..7132e71764eb0 --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs @@ -0,0 +1,8 @@ +#[path = "auxiliary/submodule.rs"] +mod submodule; + +#[cfg(test)] +mod tests { + #[test] + fn t() {} +} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr new file mode 100644 index 0000000000000..4e99876365cf8 --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr @@ -0,0 +1,14 @@ +error: items after a test module + --> $DIR/auxiliary/submodule.rs:2:1 + | +LL | mod tests {} + | ^^^^^^^^^ +LL | +LL | fn in_submodule() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::items-after-test-module` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs b/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs new file mode 100644 index 0000000000000..8ab9e8200f18a --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs @@ -0,0 +1,11 @@ +#[cfg(test)] +mod tests { + #[test] + fn f() {} +} + +#[cfg(test)] +mod more_tests { + #[test] + fn g() {} +} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed similarity index 86% rename from src/tools/clippy/tests/ui/items_after_test_module/block_module.rs rename to src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed index 5136b2557ec1a..d444100a76b92 100644 --- a/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs +++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed @@ -1,4 +1,3 @@ -//@compile-flags: --test #![allow(unused)] #![warn(clippy::items_after_test_module)] @@ -6,6 +5,13 @@ fn main() {} fn should_not_lint() {} +fn should_lint() {} + +const SHOULD_ALSO_LINT: usize = 1; +macro_rules! should_lint { + () => {}; +} + #[allow(dead_code)] #[allow(unused)] // Some attributes to check that span replacement is good enough #[allow(clippy::allow_attributes)] @@ -14,10 +20,3 @@ mod tests { #[test] fn hi() {} } - -fn should_lint() {} - -const SHOULD_ALSO_LINT: usize = 1; -macro_rules! should_not_lint { - () => {}; -} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs new file mode 100644 index 0000000000000..57da01639cca6 --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs @@ -0,0 +1,22 @@ +#![allow(unused)] +#![warn(clippy::items_after_test_module)] + +fn main() {} + +fn should_not_lint() {} + +#[allow(dead_code)] +#[allow(unused)] // Some attributes to check that span replacement is good enough +#[allow(clippy::allow_attributes)] +#[cfg(test)] +mod tests { + #[test] + fn hi() {} +} + +fn should_lint() {} + +const SHOULD_ALSO_LINT: usize = 1; +macro_rules! should_lint { + () => {}; +} diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr new file mode 100644 index 0000000000000..67bc82ebff91f --- /dev/null +++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr @@ -0,0 +1,20 @@ +error: items after a test module + --> $DIR/root_module.rs:12:1 + | +LL | mod tests { + | ^^^^^^^^^ +... +LL | fn should_lint() {} + | ^^^^^^^^^^^^^^^^ +LL | +LL | const SHOULD_ALSO_LINT: usize = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | macro_rules! should_lint { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::items-after-test-module` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]` + = help: move the items to before the test module was defined + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.rs b/src/tools/clippy/tests/ui/iter_without_into_iter.rs new file mode 100644 index 0000000000000..cedb756c79de1 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_without_into_iter.rs @@ -0,0 +1,120 @@ +//@no-rustfix +#![warn(clippy::iter_without_into_iter)] + +fn main() { + { + struct S; + impl S { + pub fn iter(&self) -> std::slice::Iter<'_, u8> { + //~^ ERROR: `iter` method without an `IntoIterator` impl + [].iter() + } + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { + //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + [].iter_mut() + } + } + } + { + struct S; + impl S { + pub fn iter(&self) -> impl Iterator { + // RPITIT is not stable, so we can't generally suggest it here yet + [].iter() + } + } + } + { + struct S<'a>(&'a mut [u8]); + impl<'a> S<'a> { + pub fn iter(&self) -> std::slice::Iter<'_, u8> { + //~^ ERROR: `iter` method without an `IntoIterator` impl + self.0.iter() + } + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { + //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + self.0.iter_mut() + } + } + } + { + // Incompatible signatures + struct S; + impl S { + pub fn iter(self) -> std::slice::Iter<'static, u8> { + todo!() + } + } + struct S2; + impl S2 { + pub async fn iter(&self) -> std::slice::Iter<'static, u8> { + todo!() + } + } + struct S3; + impl S3 { + pub fn iter(&self, _additional_param: ()) -> std::slice::Iter<'static, u8> { + todo!() + } + } + struct S4(T); + impl S4 { + pub fn iter(&self) -> std::slice::Iter<'static, (T, U)> { + todo!() + } + } + struct S5(T); + impl S5 { + pub fn iter(&self) -> std::slice::Iter<'static, T> { + todo!() + } + } + } + { + struct S(T); + impl S { + pub fn iter(&self) -> std::slice::Iter<'_, T> { + //~^ ERROR: `iter` method without an `IntoIterator` impl + todo!() + } + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { + //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + todo!() + } + } + } + { + struct S(T); + impl S { + pub fn iter(&self) -> std::slice::Iter<'_, T> { + // Don't lint, there's an existing (wrong) IntoIterator impl + todo!() + } + } + + impl<'a, T> IntoIterator for &'a S { + type Item = &'a String; + type IntoIter = std::slice::Iter<'a, String>; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } + { + struct S(T); + impl S { + pub fn iter_mut(&self) -> std::slice::IterMut<'_, T> { + // Don't lint, there's an existing (wrong) IntoIterator impl + todo!() + } + } + + impl<'a, T> IntoIterator for &'a mut S { + type Item = &'a mut String; + type IntoIter = std::slice::IterMut<'a, String>; + fn into_iter(self) -> Self::IntoIter { + todo!() + } + } + } +} diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr new file mode 100644 index 0000000000000..9d0b99415a50e --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr @@ -0,0 +1,150 @@ +error: `iter` method without an `IntoIterator` impl for `&S` + --> $DIR/iter_without_into_iter.rs:8:13 + | +LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> { +LL | | +LL | | [].iter() +LL | | } + | |_____________^ + | + = note: `-D clippy::iter-without-into-iter` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::iter_without_into_iter)]` +help: consider implementing `IntoIterator` for `&S` + | +LL ~ +LL + impl IntoIterator for &S { +LL + type IntoIter = std::slice::Iter<'_, u8>; +LL + type Iter = &u8; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter_mut` method without an `IntoIterator` impl for `&mut S` + --> $DIR/iter_without_into_iter.rs:12:13 + | +LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { +LL | | +LL | | [].iter_mut() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&mut S` + | +LL ~ +LL + impl IntoIterator for &mut S { +LL + type IntoIter = std::slice::IterMut<'_, u8>; +LL + type Iter = &mut u8; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter` method without an `IntoIterator` impl for `&S<'a>` + --> $DIR/iter_without_into_iter.rs:30:13 + | +LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> { +LL | | +LL | | self.0.iter() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&S<'a>` + | +LL ~ +LL + impl IntoIterator for &S<'a> { +LL + type IntoIter = std::slice::Iter<'_, u8>; +LL + type Iter = &u8; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter_mut` method without an `IntoIterator` impl for `&mut S<'a>` + --> $DIR/iter_without_into_iter.rs:34:13 + | +LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { +LL | | +LL | | self.0.iter_mut() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&mut S<'a>` + | +LL ~ +LL + impl IntoIterator for &mut S<'a> { +LL + type IntoIter = std::slice::IterMut<'_, u8>; +LL + type Iter = &mut u8; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter` method without an `IntoIterator` impl for `&S5` + --> $DIR/iter_without_into_iter.rs:68:13 + | +LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> { +LL | | todo!() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&S5` + | +LL ~ +LL + impl IntoIterator for &S5 { +LL + type IntoIter = std::slice::Iter<'static, T>; +LL + type Iter = &T; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter` method without an `IntoIterator` impl for `&S` + --> $DIR/iter_without_into_iter.rs:76:13 + | +LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> { +LL | | +LL | | todo!() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&S` + | +LL ~ +LL + impl IntoIterator for &S { +LL + type IntoIter = std::slice::Iter<'_, T>; +LL + type Iter = &T; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: `iter_mut` method without an `IntoIterator` impl for `&mut S` + --> $DIR/iter_without_into_iter.rs:80:13 + | +LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { +LL | | +LL | | todo!() +LL | | } + | |_____________^ + | +help: consider implementing `IntoIterator` for `&mut S` + | +LL ~ +LL + impl IntoIterator for &mut S { +LL + type IntoIter = std::slice::IterMut<'_, T>; +LL + type Iter = &mut T; +LL + fn into_iter() -> Self::IntoIter { +LL + self.iter() +LL + } +LL + } + | + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.rs b/src/tools/clippy/tests/ui/len_without_is_empty.rs index ac6c3e06365c6..d623601110e27 100644 --- a/src/tools/clippy/tests/ui/len_without_is_empty.rs +++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs @@ -436,4 +436,27 @@ impl DifferingErrors { } } +// Issue #11165 +pub struct Aliased1; +pub type Alias1 = Aliased1; + +impl Alias1 { + pub fn len(&self) -> usize { + todo!() + } + + pub fn is_empty(&self) -> bool { + todo!() + } +} + +pub struct Aliased2; +pub type Alias2 = Aliased2; +impl Alias2 { + pub fn len(&self) -> usize { + //~^ ERROR: type `Alias2` has a public `len` method, but no `is_empty` method + todo!() + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.stderr b/src/tools/clippy/tests/ui/len_without_is_empty.stderr index 4815ce6a04b29..8e51c28b33003 100644 --- a/src/tools/clippy/tests/ui/len_without_is_empty.stderr +++ b/src/tools/clippy/tests/ui/len_without_is_empty.stderr @@ -141,5 +141,11 @@ error: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no ` LL | pub async fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors +error: type `Alias2` has a public `len` method, but no `is_empty` method + --> $DIR/len_without_is_empty.rs:456:5 + | +LL | pub fn len(&self) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/let_underscore_future.rs b/src/tools/clippy/tests/ui/let_underscore_future.rs index 873ae667ab71a..c2185e9785d84 100644 --- a/src/tools/clippy/tests/ui/let_underscore_future.rs +++ b/src/tools/clippy/tests/ui/let_underscore_future.rs @@ -9,8 +9,6 @@ fn custom() -> impl Future { } fn do_something_to_future(future: &mut impl Future) {} -//~^ ERROR: this argument is a mutable reference, but not used mutably -//~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` fn main() { let _ = some_async_fn(); diff --git a/src/tools/clippy/tests/ui/let_underscore_future.stderr b/src/tools/clippy/tests/ui/let_underscore_future.stderr index 3ba99c6377b73..ef927a8083bcc 100644 --- a/src/tools/clippy/tests/ui/let_underscore_future.stderr +++ b/src/tools/clippy/tests/ui/let_underscore_future.stderr @@ -1,5 +1,5 @@ error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:16:5 + --> $DIR/let_underscore_future.rs:14:5 | LL | let _ = some_async_fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let _ = some_async_fn(); = help: to override `-D warnings` add `#[allow(clippy::let_underscore_future)]` error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:18:5 + --> $DIR/let_underscore_future.rs:16:5 | LL | let _ = custom(); | ^^^^^^^^^^^^^^^^^ @@ -17,21 +17,12 @@ LL | let _ = custom(); = help: consider awaiting the future or dropping explicitly with `std::mem::drop` error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:23:5 + --> $DIR/let_underscore_future.rs:21:5 | LL | let _ = future; | ^^^^^^^^^^^^^^^ | = help: consider awaiting the future or dropping explicitly with `std::mem::drop` -error: this argument is a mutable reference, but not used mutably - --> $DIR/let_underscore_future.rs:11:35 - | -LL | fn do_something_to_future(future: &mut impl Future) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&impl Future` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed index 57374bd5fcdad..f98ce9d50a994 100644 --- a/src/tools/clippy/tests/ui/let_unit.fixed +++ b/src/tools/clippy/tests/ui/let_unit.fixed @@ -177,3 +177,5 @@ fn attributes() { async fn issue10433() { let _pending: () = std::future::pending().await; } + +pub async fn issue11502(a: ()) {} diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs index 09077c60d5019..6d942ca8908c4 100644 --- a/src/tools/clippy/tests/ui/let_unit.rs +++ b/src/tools/clippy/tests/ui/let_unit.rs @@ -177,3 +177,5 @@ fn attributes() { async fn issue10433() { let _pending: () = std::future::pending().await; } + +pub async fn issue11502(a: ()) {} diff --git a/src/tools/clippy/tests/ui/manual_hash_one.fixed b/src/tools/clippy/tests/ui/manual_hash_one.fixed new file mode 100644 index 0000000000000..edfd9c4a47bba --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_hash_one.fixed @@ -0,0 +1,89 @@ +#![warn(clippy::manual_hash_one)] +#![allow(clippy::needless_borrows_for_generic_args)] + +use std::hash::{BuildHasher, Hash, Hasher}; + +fn returned(b: impl BuildHasher) -> u64 { + + + b.hash_one(&true) +} + +fn unsized_receiver(b: impl BuildHasher, s: &str) { + + + let _ = b.hash_one(&s[4..10]); +} + +fn owned_value(b: impl BuildHasher, v: Vec) -> Vec { + + + let _ = b.hash_one(&v); + v +} + +fn reused_hasher(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + let _ = hasher.finish(); +} + +fn reused_hasher_in_return(b: impl BuildHasher) -> u64 { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + hasher.finish() +} + +fn no_hash(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + let _ = hasher.finish(); +} + +fn hash_twice(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + true.hash(&mut hasher); + let _ = hasher.finish(); +} + +fn other_hasher(b: impl BuildHasher) { + let mut other_hasher = b.build_hasher(); + + let mut hasher = b.build_hasher(); + true.hash(&mut other_hasher); + let _ = hasher.finish(); +} + +fn finish_then_hash(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + let _ = hasher.finish(); + true.hash(&mut hasher); +} + +fn in_macro(b: impl BuildHasher) { + macro_rules! m { + ($b:expr) => {{ + let mut hasher = $b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + }}; + } + + m!(b); +} + +#[clippy::msrv = "1.70"] +fn msrv_1_70(b: impl BuildHasher, v: impl Hash) { + let mut hasher = b.build_hasher(); + v.hash(&mut hasher); + let _ = hasher.finish(); +} + +#[clippy::msrv = "1.71"] +fn msrv_1_71(b: impl BuildHasher, v: impl Hash) { + + + let _ = b.hash_one(&v); +} diff --git a/src/tools/clippy/tests/ui/manual_hash_one.rs b/src/tools/clippy/tests/ui/manual_hash_one.rs new file mode 100644 index 0000000000000..ee61522853f0f --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_hash_one.rs @@ -0,0 +1,89 @@ +#![warn(clippy::manual_hash_one)] +#![allow(clippy::needless_borrows_for_generic_args)] + +use std::hash::{BuildHasher, Hash, Hasher}; + +fn returned(b: impl BuildHasher) -> u64 { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + hasher.finish() +} + +fn unsized_receiver(b: impl BuildHasher, s: &str) { + let mut hasher = b.build_hasher(); + s[4..10].hash(&mut hasher); + let _ = hasher.finish(); +} + +fn owned_value(b: impl BuildHasher, v: Vec) -> Vec { + let mut hasher = b.build_hasher(); + v.hash(&mut hasher); + let _ = hasher.finish(); + v +} + +fn reused_hasher(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + let _ = hasher.finish(); +} + +fn reused_hasher_in_return(b: impl BuildHasher) -> u64 { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + hasher.finish() +} + +fn no_hash(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + let _ = hasher.finish(); +} + +fn hash_twice(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + true.hash(&mut hasher); + true.hash(&mut hasher); + let _ = hasher.finish(); +} + +fn other_hasher(b: impl BuildHasher) { + let mut other_hasher = b.build_hasher(); + + let mut hasher = b.build_hasher(); + true.hash(&mut other_hasher); + let _ = hasher.finish(); +} + +fn finish_then_hash(b: impl BuildHasher) { + let mut hasher = b.build_hasher(); + let _ = hasher.finish(); + true.hash(&mut hasher); +} + +fn in_macro(b: impl BuildHasher) { + macro_rules! m { + ($b:expr) => {{ + let mut hasher = $b.build_hasher(); + true.hash(&mut hasher); + let _ = hasher.finish(); + }}; + } + + m!(b); +} + +#[clippy::msrv = "1.70"] +fn msrv_1_70(b: impl BuildHasher, v: impl Hash) { + let mut hasher = b.build_hasher(); + v.hash(&mut hasher); + let _ = hasher.finish(); +} + +#[clippy::msrv = "1.71"] +fn msrv_1_71(b: impl BuildHasher, v: impl Hash) { + let mut hasher = b.build_hasher(); + v.hash(&mut hasher); + let _ = hasher.finish(); +} diff --git a/src/tools/clippy/tests/ui/manual_hash_one.stderr b/src/tools/clippy/tests/ui/manual_hash_one.stderr new file mode 100644 index 0000000000000..3ce6f41e1f910 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_hash_one.stderr @@ -0,0 +1,56 @@ +error: manual implementation of `BuildHasher::hash_one` + --> $DIR/manual_hash_one.rs:9:5 + | +LL | hasher.finish() + | ^^^^^^^^^^^^^^^ + | + = note: `-D clippy::manual-hash-one` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_hash_one)]` +help: try + | +LL ~ +LL ~ +LL ~ b.hash_one(&true) + | + +error: manual implementation of `BuildHasher::hash_one` + --> $DIR/manual_hash_one.rs:15:13 + | +LL | let _ = hasher.finish(); + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ +LL ~ +LL ~ let _ = b.hash_one(&s[4..10]); + | + +error: manual implementation of `BuildHasher::hash_one` + --> $DIR/manual_hash_one.rs:21:13 + | +LL | let _ = hasher.finish(); + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ +LL ~ +LL ~ let _ = b.hash_one(&v); + | + +error: manual implementation of `BuildHasher::hash_one` + --> $DIR/manual_hash_one.rs:88:13 + | +LL | let _ = hasher.finish(); + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ +LL ~ +LL ~ let _ = b.hash_one(&v); + | + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.fixed b/src/tools/clippy/tests/ui/manual_let_else_match.fixed index 09b713f04101e..588ba5edd8f15 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_match.fixed +++ b/src/tools/clippy/tests/ui/manual_let_else_match.fixed @@ -133,3 +133,7 @@ fn not_fire() { [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data, }; } + +fn issue11579() { + let Some(msg) = Some("hi") else { unreachable!("can't happen") }; +} diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs index e6af47384200e..c37b5613ff7d5 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_match.rs +++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs @@ -170,3 +170,11 @@ fn not_fire() { [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data, }; } + +fn issue11579() { + let msg = match Some("hi") { + //~^ ERROR: this could be rewritten as `let...else` + Some(m) => m, + _ => unreachable!("can't happen"), + }; +} diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr index 8ca2c84072d0f..18bfe324ba76a 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr @@ -92,5 +92,15 @@ LL | | _ => return, LL | | }; | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };` -error: aborting due to 9 previous errors +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_match.rs:175:5 + | +LL | / let msg = match Some("hi") { +LL | | +LL | | Some(m) => m, +LL | | _ => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let Some(msg) = Some("hi") else { unreachable!("can't happen") };` + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed index f6a964da418a2..16cee3fd38236 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.fixed +++ b/src/tools/clippy/tests/ui/manual_map_option.fixed @@ -5,6 +5,7 @@ clippy::unit_arg, clippy::match_ref_pats, clippy::redundant_pattern_matching, + clippy::unnecessary_map_on_constructor, for_loops_over_fallibles, dead_code )] diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs index df9dc256d3038..4655acf1406c7 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.rs +++ b/src/tools/clippy/tests/ui/manual_map_option.rs @@ -5,6 +5,7 @@ clippy::unit_arg, clippy::match_ref_pats, clippy::redundant_pattern_matching, + clippy::unnecessary_map_on_constructor, for_loops_over_fallibles, dead_code )] diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr index ff6ed974d4a12..3754a982cb9bc 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.stderr +++ b/src/tools/clippy/tests/ui/manual_map_option.stderr @@ -1,5 +1,5 @@ error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:13:5 + --> $DIR/manual_map_option.rs:14:5 | LL | / match Some(0) { LL | | Some(_) => Some(2), @@ -11,7 +11,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_map)]` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:18:5 + --> $DIR/manual_map_option.rs:19:5 | LL | / match Some(0) { LL | | Some(x) => Some(x + 1), @@ -20,7 +20,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| x + 1)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:23:5 + --> $DIR/manual_map_option.rs:24:5 | LL | / match Some("") { LL | | Some(x) => Some(x.is_empty()), @@ -29,7 +29,7 @@ LL | | }; | |_____^ help: try: `Some("").map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:28:5 + --> $DIR/manual_map_option.rs:29:5 | LL | / if let Some(x) = Some(0) { LL | | Some(!x) @@ -39,7 +39,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| !x)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:35:5 + --> $DIR/manual_map_option.rs:36:5 | LL | / match Some(0) { LL | | Some(x) => { Some(std::convert::identity(x)) } @@ -48,7 +48,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(std::convert::identity)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:40:5 + --> $DIR/manual_map_option.rs:41:5 | LL | / match Some(&String::new()) { LL | | Some(x) => Some(str::len(x)), @@ -57,7 +57,7 @@ LL | | }; | |_____^ help: try: `Some(&String::new()).map(|x| str::len(x))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:50:5 + --> $DIR/manual_map_option.rs:51:5 | LL | / match &Some([0, 1]) { LL | | Some(x) => Some(x[0]), @@ -66,7 +66,7 @@ LL | | }; | |_____^ help: try: `Some([0, 1]).as_ref().map(|x| x[0])` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:55:5 + --> $DIR/manual_map_option.rs:56:5 | LL | / match &Some(0) { LL | | &Some(x) => Some(x * 2), @@ -75,7 +75,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| x * 2)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:60:5 + --> $DIR/manual_map_option.rs:61:5 | LL | / match Some(String::new()) { LL | | Some(ref x) => Some(x.is_empty()), @@ -84,7 +84,7 @@ LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:65:5 + --> $DIR/manual_map_option.rs:66:5 | LL | / match &&Some(String::new()) { LL | | Some(x) => Some(x.len()), @@ -93,7 +93,7 @@ LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:70:5 + --> $DIR/manual_map_option.rs:71:5 | LL | / match &&Some(0) { LL | | &&Some(x) => Some(x + x), @@ -102,7 +102,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| x + x)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:83:9 + --> $DIR/manual_map_option.rs:84:9 | LL | / match &mut Some(String::new()) { LL | | Some(x) => Some(x.push_str("")), @@ -111,7 +111,7 @@ LL | | }; | |_________^ help: try: `Some(String::new()).as_mut().map(|x| x.push_str(""))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:89:5 + --> $DIR/manual_map_option.rs:90:5 | LL | / match &mut Some(String::new()) { LL | | Some(ref x) => Some(x.len()), @@ -120,7 +120,7 @@ LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:94:5 + --> $DIR/manual_map_option.rs:95:5 | LL | / match &mut &Some(String::new()) { LL | | Some(x) => Some(x.is_empty()), @@ -129,7 +129,7 @@ LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:99:5 + --> $DIR/manual_map_option.rs:100:5 | LL | / match Some((0, 1, 2)) { LL | | Some((x, y, z)) => Some(x + y + z), @@ -138,7 +138,7 @@ LL | | }; | |_____^ help: try: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:104:5 + --> $DIR/manual_map_option.rs:105:5 | LL | / match Some([1, 2, 3]) { LL | | Some([first, ..]) => Some(first), @@ -147,7 +147,7 @@ LL | | }; | |_____^ help: try: `Some([1, 2, 3]).map(|[first, ..]| first)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:109:5 + --> $DIR/manual_map_option.rs:110:5 | LL | / match &Some((String::new(), "test")) { LL | | Some((x, y)) => Some((y, x)), @@ -156,7 +156,7 @@ LL | | }; | |_____^ help: try: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:167:5 + --> $DIR/manual_map_option.rs:168:5 | LL | / match Some(0) { LL | | Some(x) => Some(vec![x]), @@ -165,7 +165,7 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| vec![x])` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:172:5 + --> $DIR/manual_map_option.rs:173:5 | LL | / match option_env!("") { LL | | Some(x) => Some(String::from(x)), @@ -174,7 +174,7 @@ LL | | }; | |_____^ help: try: `option_env!("").map(String::from)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:192:12 + --> $DIR/manual_map_option.rs:193:12 | LL | } else if let Some(x) = Some(0) { | ____________^ @@ -185,7 +185,7 @@ LL | | }; | |_____^ help: try: `{ Some(0).map(|x| x + 1) }` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:200:12 + --> $DIR/manual_map_option.rs:201:12 | LL | } else if let Some(x) = Some(0) { | ____________^ diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs index 0e439dabfd651..e32ba8631761b 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs @@ -10,10 +10,9 @@ enum E { _C, } -// user forgot to remove the marker +// if the user explicitly marks as nonexhaustive we shouldn't warn them #[non_exhaustive] enum Ep { - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern A, B, #[doc(hidden)] diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr index ce7e21c94bbdc..7361a4a2cbbe8 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr @@ -22,23 +22,5 @@ LL | _C, = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]` -error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive_enum.rs:15:1 - | -LL | / enum Ep { -LL | | -LL | | A, -LL | | B, -LL | | #[doc(hidden)] -LL | | _C, -LL | | } - | |_^ - | -help: remove this variant - --> $DIR/manual_non_exhaustive_enum.rs:20:5 - | -LL | _C, - | ^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs index 1ee048bf7f6c3..e1b95aa577604 100644 --- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs +++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs @@ -4,14 +4,18 @@ //@no-rustfix use std::sync::atomic::Ordering; // #[non_exhaustive] enum +fn repeat() -> ! { + panic!() +} + pub fn f(x: Ordering) { match x { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - Ordering::AcqRel | Ordering::SeqCst => panic!(), + Ordering::AcqRel | Ordering::SeqCst => repeat(), #[deny(non_exhaustive_omitted_patterns)] - _ => panic!(), + _ => repeat(), } } @@ -25,8 +29,8 @@ mod f { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - Ordering::AcqRel | Ordering::SeqCst => panic!(), - _ => panic!(), + Ordering::AcqRel | Ordering::SeqCst => repeat(), + _ => repeat(), } } } @@ -38,9 +42,9 @@ pub fn g(x: Ordering) { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - Ordering::AcqRel | Ordering::SeqCst => panic!(), + Ordering::AcqRel | Ordering::SeqCst => repeat(), //~^ ERROR: this match arm has an identical body to the `_` wildcard arm - _ => panic!(), + _ => repeat(), } } @@ -52,9 +56,9 @@ mod g { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - Ordering::AcqRel | Ordering::SeqCst => panic!(), + Ordering::AcqRel | Ordering::SeqCst => repeat(), //~^ ERROR: this match arm has an identical body to the `_` wildcard arm - _ => panic!(), + _ => repeat(), } } } diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr index a039536338bcb..ae6b02ab1b507 100644 --- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr +++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr @@ -1,29 +1,29 @@ error: this match arm has an identical body to the `_` wildcard arm - --> $DIR/match_same_arms_non_exhaustive.rs:41:9 + --> $DIR/match_same_arms_non_exhaustive.rs:45:9 | -LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), +LL | Ordering::AcqRel | Ordering::SeqCst => repeat(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> $DIR/match_same_arms_non_exhaustive.rs:43:9 + --> $DIR/match_same_arms_non_exhaustive.rs:47:9 | -LL | _ => panic!(), +LL | _ => repeat(), | ^^^^^^^^^^^^^ = note: `-D clippy::match-same-arms` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]` error: this match arm has an identical body to the `_` wildcard arm - --> $DIR/match_same_arms_non_exhaustive.rs:55:13 + --> $DIR/match_same_arms_non_exhaustive.rs:59:13 | -LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), +LL | Ordering::AcqRel | Ordering::SeqCst => repeat(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> $DIR/match_same_arms_non_exhaustive.rs:57:13 + --> $DIR/match_same_arms_non_exhaustive.rs:61:13 | -LL | _ => panic!(), +LL | _ => repeat(), | ^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/must_use_unit.stderr b/src/tools/clippy/tests/ui/must_use_unit.stderr index e67d9b5b9d8d3..f2ee185857d3e 100644 --- a/src/tools/clippy/tests/ui/must_use_unit.stderr +++ b/src/tools/clippy/tests/ui/must_use_unit.stderr @@ -4,7 +4,7 @@ error: this unit-returning function has a `#[must_use]` attribute LL | #[must_use] | ----------- help: remove the attribute LL | pub fn must_use_default() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::must-use-unit` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]` @@ -23,7 +23,7 @@ error: this unit-returning function has a `#[must_use]` attribute LL | #[must_use = "With note"] | ------------------------- help: remove the attribute LL | pub fn must_use_with_note() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/mut_key.rs b/src/tools/clippy/tests/ui/mut_key.rs index 8069213217683..2d70bfd4c770c 100644 --- a/src/tools/clippy/tests/ui/mut_key.rs +++ b/src/tools/clippy/tests/ui/mut_key.rs @@ -32,8 +32,6 @@ fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet = HashMap::new(); //~^ ERROR: mutable key type m.keys().cloned().collect() diff --git a/src/tools/clippy/tests/ui/mut_key.stderr b/src/tools/clippy/tests/ui/mut_key.stderr index 3701769a9ca7f..48eeaff78a789 100644 --- a/src/tools/clippy/tests/ui/mut_key.stderr +++ b/src/tools/clippy/tests/ui/mut_key.stderr @@ -14,103 +14,94 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash | ^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:37:5 + --> $DIR/mut_key.rs:35:5 | LL | let _other: HashMap = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:65:22 + --> $DIR/mut_key.rs:63:22 | LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:78:5 + --> $DIR/mut_key.rs:76:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:80:5 + --> $DIR/mut_key.rs:78:5 | LL | let _map = HashMap::<&mut Cell, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:82:5 + --> $DIR/mut_key.rs:80:5 | LL | let _map = HashMap::<&mut usize, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:85:5 + --> $DIR/mut_key.rs:83:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:87:5 + --> $DIR/mut_key.rs:85:5 | LL | let _map = HashMap::, ()>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:89:5 + --> $DIR/mut_key.rs:87:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:91:5 + --> $DIR/mut_key.rs:89:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:93:5 + --> $DIR/mut_key.rs:91:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:95:5 + --> $DIR/mut_key.rs:93:5 | LL | let _map = HashMap::>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:97:5 + --> $DIR/mut_key.rs:95:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:100:5 + --> $DIR/mut_key.rs:98:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:102:5 + --> $DIR/mut_key.rs:100:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:104:5 + --> $DIR/mut_key.rs:102:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/mut_key.rs:31:32 - | -LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&HashMap` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/mut_reference.rs b/src/tools/clippy/tests/ui/mut_reference.rs index f3db226e4e7fc..1d7faaa5e75e4 100644 --- a/src/tools/clippy/tests/ui/mut_reference.rs +++ b/src/tools/clippy/tests/ui/mut_reference.rs @@ -22,8 +22,6 @@ impl MyStruct { fn takes_an_immutable_reference(&self, a: &i32) {} fn takes_a_mutable_reference(&self, a: &mut i32) {} - //~^ ERROR: this argument is a mutable reference, but not used mutably - //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` } #[warn(clippy::unnecessary_mut_passed)] diff --git a/src/tools/clippy/tests/ui/mut_reference.stderr b/src/tools/clippy/tests/ui/mut_reference.stderr index d7a0d0c225250..87db08e2a7420 100644 --- a/src/tools/clippy/tests/ui/mut_reference.stderr +++ b/src/tools/clippy/tests/ui/mut_reference.stderr @@ -1,5 +1,5 @@ error: the function `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:32:34 + --> $DIR/mut_reference.rs:30:34 | LL | takes_an_immutable_reference(&mut 42); | ^^^^^^^ @@ -8,25 +8,16 @@ LL | takes_an_immutable_reference(&mut 42); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_mut_passed)]` error: the function `as_ptr` doesn't need a mutable reference - --> $DIR/mut_reference.rs:36:12 + --> $DIR/mut_reference.rs:34:12 | LL | as_ptr(&mut 42); | ^^^^^^^ error: the method `takes_an_immutable_reference` doesn't need a mutable reference - --> $DIR/mut_reference.rs:41:44 + --> $DIR/mut_reference.rs:39:44 | LL | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/mut_reference.rs:24:44 - | -LL | fn takes_a_mutable_reference(&self, a: &mut i32) {} - | ^^^^^^^^ help: consider changing to: `&i32` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index 0a52b25229d76..c2c5f765abfff 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -131,21 +131,6 @@ fn main() { 0 } } - - let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap(); - let _ = std::path::Path::new(".").join("."); - deref_target_is_x(X); - multiple_constraints([[""]]); - multiple_constraints_normalizes_to_same(X, X); - let _ = Some("").unwrap_or(""); - let _ = std::fs::write("x", "".to_string()); - - only_sized(&""); // Don't lint. `Sized` is only bound - let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound - let _ = Box::new(&""); // Don't lint. Type parameter appears in return type - ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter - refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't - multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments } #[allow(clippy::needless_borrowed_reference)] @@ -201,103 +186,6 @@ mod issue9160 { } } -#[derive(Clone, Copy)] -struct X; - -impl std::ops::Deref for X { - type Target = X; - fn deref(&self) -> &Self::Target { - self - } -} - -fn deref_target_is_x(_: T) -where - T: std::ops::Deref, -{ -} - -fn multiple_constraints(_: T) -where - T: IntoIterator + IntoIterator, - U: IntoIterator, - V: AsRef, - X: IntoIterator, - Y: AsRef, -{ -} - -fn multiple_constraints_normalizes_to_same(_: T, _: V) -where - T: std::ops::Deref, - U: std::ops::Deref, -{ -} - -fn only_sized(_: T) {} - -fn ref_as_ref_path(_: &'static T) -where - &'static T: AsRef, -{ -} - -trait RefsOnly { - type Referent; -} - -impl RefsOnly for &T { - type Referent = T; -} - -fn refs_only(_: T) -where - T: RefsOnly, -{ -} - -fn multiple_constraints_normalizes_to_different(_: T, _: U) -where - T: IntoIterator, - U: IntoIterator, - V: AsRef, -{ -} - -// https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 -mod copyable_iterator { - #[derive(Clone, Copy)] - struct Iter; - impl Iterator for Iter { - type Item = (); - fn next(&mut self) -> Option { - None - } - } - fn takes_iter(_: impl Iterator) {} - fn dont_warn(mut x: Iter) { - takes_iter(&mut x); - } - #[allow(unused_mut)] - fn warn(mut x: &mut Iter) { - takes_iter(x) - } -} - -#[clippy::msrv = "1.52.0"] -mod under_msrv { - fn foo() { - let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - } -} - -#[clippy::msrv = "1.53.0"] -mod meets_msrv { - fn foo() { - let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap(); - } -} - fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; @@ -326,184 +214,6 @@ fn issue9383() { } } -fn closure_test() { - let env = "env".to_owned(); - let arg = "arg".to_owned(); - let f = |arg| { - let loc = "loc".to_owned(); - let _ = std::fs::write("x", &env); // Don't lint. In environment - let _ = std::fs::write("x", arg); - let _ = std::fs::write("x", loc); - }; - let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f` - f(arg); -} - -mod significant_drop { - #[derive(Debug)] - struct X; - - #[derive(Debug)] - struct Y; - - impl Drop for Y { - fn drop(&mut self) {} - } - - fn foo(x: X, y: Y) { - debug(x); - debug(&y); // Don't lint. Has significant drop - } - - fn debug(_: impl std::fmt::Debug) {} -} - -mod used_exactly_once { - fn foo(x: String) { - use_x(x); - } - fn use_x(_: impl AsRef) {} -} - -mod used_more_than_once { - fn foo(x: String) { - use_x(&x); - use_x_again(&x); - } - fn use_x(_: impl AsRef) {} - fn use_x_again(_: impl AsRef) {} -} - -// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 -mod issue_9111 { - struct A; - - impl Extend for A { - fn extend>(&mut self, _: T) { - unimplemented!() - } - } - - impl<'a> Extend<&'a u8> for A { - fn extend>(&mut self, _: T) { - unimplemented!() - } - } - - fn main() { - let mut a = A; - a.extend(&[]); // vs a.extend([]); - } -} - -mod issue_9710 { - fn main() { - let string = String::new(); - for _i in 0..10 { - f(&string); - } - } - - fn f>(_: T) {} -} - -mod issue_9739 { - fn foo(_it: impl IntoIterator) {} - - fn main() { - foo(if std::env::var_os("HI").is_some() { - &[0] - } else { - &[] as &[u32] - }); - } -} - -mod issue_9739_method_variant { - struct S; - - impl S { - fn foo(&self, _it: impl IntoIterator) {} - } - - fn main() { - S.foo(if std::env::var_os("HI").is_some() { - &[0] - } else { - &[] as &[u32] - }); - } -} - -mod issue_9782 { - fn foo>(t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - // 100 - foo::<[u8; 100]>(a); - foo(a); - - // 16 - foo::<&[u8]>(&a); - foo(a.as_slice()); - - // 8 - foo::<&[u8; 100]>(&a); - foo(a); - } -} - -mod issue_9782_type_relative_variant { - struct S; - - impl S { - fn foo>(t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - S::foo::<&[u8; 100]>(&a); - } -} - -mod issue_9782_method_variant { - struct S; - - impl S { - fn foo>(&self, t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - S.foo::<&[u8; 100]>(&a); - } -} - -mod issue_10535 { - static SOME_STATIC: String = String::new(); - - static UNIT: () = compute(&SOME_STATIC); - - pub const fn compute(_: T) - where - T: Copy, - { - } -} - mod issue_10253 { struct S; trait X { diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 34a95d184635d..0cd6e41b8a47a 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -131,21 +131,6 @@ fn main() { 0 } } - - let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - let _ = std::path::Path::new(".").join(&&"."); - deref_target_is_x(&X); - multiple_constraints(&[[""]]); - multiple_constraints_normalizes_to_same(&X, X); - let _ = Some("").unwrap_or(&""); - let _ = std::fs::write("x", &"".to_string()); - - only_sized(&""); // Don't lint. `Sized` is only bound - let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound - let _ = Box::new(&""); // Don't lint. Type parameter appears in return type - ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter - refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't - multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments } #[allow(clippy::needless_borrowed_reference)] @@ -201,103 +186,6 @@ mod issue9160 { } } -#[derive(Clone, Copy)] -struct X; - -impl std::ops::Deref for X { - type Target = X; - fn deref(&self) -> &Self::Target { - self - } -} - -fn deref_target_is_x(_: T) -where - T: std::ops::Deref, -{ -} - -fn multiple_constraints(_: T) -where - T: IntoIterator + IntoIterator, - U: IntoIterator, - V: AsRef, - X: IntoIterator, - Y: AsRef, -{ -} - -fn multiple_constraints_normalizes_to_same(_: T, _: V) -where - T: std::ops::Deref, - U: std::ops::Deref, -{ -} - -fn only_sized(_: T) {} - -fn ref_as_ref_path(_: &'static T) -where - &'static T: AsRef, -{ -} - -trait RefsOnly { - type Referent; -} - -impl RefsOnly for &T { - type Referent = T; -} - -fn refs_only(_: T) -where - T: RefsOnly, -{ -} - -fn multiple_constraints_normalizes_to_different(_: T, _: U) -where - T: IntoIterator, - U: IntoIterator, - V: AsRef, -{ -} - -// https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 -mod copyable_iterator { - #[derive(Clone, Copy)] - struct Iter; - impl Iterator for Iter { - type Item = (); - fn next(&mut self) -> Option { - None - } - } - fn takes_iter(_: impl Iterator) {} - fn dont_warn(mut x: Iter) { - takes_iter(&mut x); - } - #[allow(unused_mut)] - fn warn(mut x: &mut Iter) { - takes_iter(&mut x) - } -} - -#[clippy::msrv = "1.52.0"] -mod under_msrv { - fn foo() { - let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - } -} - -#[clippy::msrv = "1.53.0"] -mod meets_msrv { - fn foo() { - let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - } -} - fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; @@ -326,184 +214,6 @@ fn issue9383() { } } -fn closure_test() { - let env = "env".to_owned(); - let arg = "arg".to_owned(); - let f = |arg| { - let loc = "loc".to_owned(); - let _ = std::fs::write("x", &env); // Don't lint. In environment - let _ = std::fs::write("x", &arg); - let _ = std::fs::write("x", &loc); - }; - let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f` - f(arg); -} - -mod significant_drop { - #[derive(Debug)] - struct X; - - #[derive(Debug)] - struct Y; - - impl Drop for Y { - fn drop(&mut self) {} - } - - fn foo(x: X, y: Y) { - debug(&x); - debug(&y); // Don't lint. Has significant drop - } - - fn debug(_: impl std::fmt::Debug) {} -} - -mod used_exactly_once { - fn foo(x: String) { - use_x(&x); - } - fn use_x(_: impl AsRef) {} -} - -mod used_more_than_once { - fn foo(x: String) { - use_x(&x); - use_x_again(&x); - } - fn use_x(_: impl AsRef) {} - fn use_x_again(_: impl AsRef) {} -} - -// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 -mod issue_9111 { - struct A; - - impl Extend for A { - fn extend>(&mut self, _: T) { - unimplemented!() - } - } - - impl<'a> Extend<&'a u8> for A { - fn extend>(&mut self, _: T) { - unimplemented!() - } - } - - fn main() { - let mut a = A; - a.extend(&[]); // vs a.extend([]); - } -} - -mod issue_9710 { - fn main() { - let string = String::new(); - for _i in 0..10 { - f(&string); - } - } - - fn f>(_: T) {} -} - -mod issue_9739 { - fn foo(_it: impl IntoIterator) {} - - fn main() { - foo(if std::env::var_os("HI").is_some() { - &[0] - } else { - &[] as &[u32] - }); - } -} - -mod issue_9739_method_variant { - struct S; - - impl S { - fn foo(&self, _it: impl IntoIterator) {} - } - - fn main() { - S.foo(if std::env::var_os("HI").is_some() { - &[0] - } else { - &[] as &[u32] - }); - } -} - -mod issue_9782 { - fn foo>(t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - // 100 - foo::<[u8; 100]>(a); - foo(a); - - // 16 - foo::<&[u8]>(&a); - foo(a.as_slice()); - - // 8 - foo::<&[u8; 100]>(&a); - foo(&a); - } -} - -mod issue_9782_type_relative_variant { - struct S; - - impl S { - fn foo>(t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - S::foo::<&[u8; 100]>(&a); - } -} - -mod issue_9782_method_variant { - struct S; - - impl S { - fn foo>(&self, t: T) { - println!("{}", std::mem::size_of::()); - let _t: &[u8] = t.as_ref(); - } - } - - fn main() { - let a: [u8; 100] = [0u8; 100]; - - S.foo::<&[u8; 100]>(&a); - } -} - -mod issue_10535 { - static SOME_STATIC: String = String::new(); - - static UNIT: () = compute(&SOME_STATIC); - - pub const fn compute(_: T) - where - T: Copy, - { - } -} - mod issue_10253 { struct S; trait X { diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index 8e27014d53c3e..e91b78b0a1520 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -121,101 +121,17 @@ error: this expression creates a reference which is immediately dereferenced by LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:135:51 - | -LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:136:44 - | -LL | let _ = std::path::Path::new(".").join(&&"."); - | ^^^^^ help: change this to: `"."` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:137:23 - | -LL | deref_target_is_x(&X); - | ^^ help: change this to: `X` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:138:26 - | -LL | multiple_constraints(&[[""]]); - | ^^^^^^^ help: change this to: `[[""]]` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:139:45 - | -LL | multiple_constraints_normalizes_to_same(&X, X); - | ^^ help: change this to: `X` - -error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:140:32 - | -LL | let _ = Some("").unwrap_or(&""); - | ^^^ help: change this to: `""` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:141:33 - | -LL | let _ = std::fs::write("x", &"".to_string()); - | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` - error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:190:13 + --> $DIR/needless_borrow.rs:175:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:199:13 + --> $DIR/needless_borrow.rs:184:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:283:20 - | -LL | takes_iter(&mut x) - | ^^^^^^ help: change this to: `x` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:297:55 - | -LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); - | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:335:37 - | -LL | let _ = std::fs::write("x", &arg); - | ^^^^ help: change this to: `arg` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:336:37 - | -LL | let _ = std::fs::write("x", &loc); - | ^^^^ help: change this to: `loc` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:354:15 - | -LL | debug(&x); - | ^^ help: change this to: `x` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:363:15 - | -LL | use_x(&x); - | ^^ help: change this to: `x` - -error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:457:13 - | -LL | foo(&a); - | ^^ help: change this to: `a` - -error: aborting due to 36 previous errors +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed new file mode 100644 index 0000000000000..2a335516f51c3 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed @@ -0,0 +1,287 @@ +#![warn(clippy::needless_borrows_for_generic_args)] +#![allow( + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap, + clippy::needless_borrow +)] + +use core::ops::Deref; +use std::any::Any; +use std::ffi::OsStr; +use std::fmt::{Debug, Display}; +use std::path::Path; +use std::process::Command; + +fn main() { + let _ = Command::new("ls").args(["-a", "-l"]).status().unwrap(); + let _ = Path::new(".").join("."); + let _ = Any::type_id(&""); // Don't lint. `Any` is only bound + let _ = Box::new(&""); // Don't lint. Type parameter appears in return type + let _ = Some("").unwrap_or(&""); + let _ = std::fs::write("x", "".to_string()); + + { + #[derive(Clone, Copy)] + struct X; + + impl Deref for X { + type Target = X; + fn deref(&self) -> &Self::Target { + self + } + } + + fn deref_target_is_x>(_: T) {} + + deref_target_is_x(X); + } + { + fn multiple_constraints(_: T) + where + T: IntoIterator + IntoIterator, + U: IntoIterator, + V: AsRef, + X: IntoIterator, + Y: AsRef, + { + } + + multiple_constraints([[""]]); + } + { + #[derive(Clone, Copy)] + struct X; + + impl Deref for X { + type Target = X; + fn deref(&self) -> &Self::Target { + self + } + } + + fn multiple_constraints_normalizes_to_same(_: T, _: V) + where + T: Deref, + U: Deref, + { + } + + multiple_constraints_normalizes_to_same(X, X); + } + { + fn only_sized(_: T) {} + only_sized(&""); // Don't lint. `Sized` is only bound + } + { + fn ref_as_ref_path(_: &'static T) + where + &'static T: AsRef, + { + } + + ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter + } + { + trait RefsOnly { + type Referent; + } + + impl RefsOnly for &T { + type Referent = T; + } + + fn refs_only(_: T) + where + T: RefsOnly, + { + } + + refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't + } + { + fn multiple_constraints_normalizes_to_different(_: T, _: U) + where + T: IntoIterator, + U: IntoIterator, + V: AsRef, + { + } + multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments + } + // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 + { + #[derive(Clone, Copy)] + struct Iter; + impl Iterator for Iter { + type Item = (); + fn next(&mut self) -> Option { + None + } + } + fn takes_iter(_: impl Iterator) {} + fn dont_warn(mut x: Iter) { + takes_iter(&mut x); + } + #[allow(unused_mut)] + fn warn(mut x: &mut Iter) { + takes_iter(x) + } + } + #[clippy::msrv = "1.52.0"] + { + let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + }; + #[clippy::msrv = "1.53.0"] + { + let _ = Command::new("ls").args(["-a", "-l"]).status().unwrap(); + }; + { + let env = "env".to_owned(); + let arg = "arg".to_owned(); + let f = |arg| { + let loc = "loc".to_owned(); + let _ = std::fs::write("x", &env); // Don't lint. In environment + let _ = std::fs::write("x", arg); + let _ = std::fs::write("x", loc); + }; + let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f` + f(arg); + } + { + #[derive(Debug)] + struct X; + + impl Drop for X { + fn drop(&mut self) {} + } + + fn f(_: impl Debug) {} + + let x = X; + f(&x); // Don't lint. Has significant drop + } + { + fn f(_: impl AsRef) {} + + let x = String::new(); + f(x); + } + { + fn f(_: impl AsRef) {} + fn f2(_: impl AsRef) {} + + let x = String::new(); + f(&x); + f2(&x); + } + // https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 + // issue 9111 + { + struct A; + + impl Extend for A { + fn extend>(&mut self, _: T) { + unimplemented!() + } + } + + impl<'a> Extend<&'a u8> for A { + fn extend>(&mut self, _: T) { + unimplemented!() + } + } + + let mut a = A; + a.extend(&[]); // vs a.extend([]); + } + // issue 9710 + { + fn f(_: impl AsRef) {} + + let x = String::new(); + for _ in 0..10 { + f(&x); + } + } + // issue 9739 + { + fn foo(_it: impl IntoIterator) {} + foo(if std::env::var_os("HI").is_some() { + &[0] + } else { + &[] as &[u32] + }); + } + { + struct S; + + impl S { + fn foo(&self, _it: impl IntoIterator) {} + } + + S.foo(if std::env::var_os("HI").is_some() { + &[0] + } else { + &[] as &[u32] + }); + } + // issue 9782 + { + fn foo>(t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + + let a: [u8; 100] = [0u8; 100]; + + // 100 + foo::<[u8; 100]>(a); + foo(a); + + // 16 + foo::<&[u8]>(&a); + foo(a.as_slice()); + + // 8 + foo::<&[u8; 100]>(&a); + foo(a); + } + { + struct S; + + impl S { + fn foo>(t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + } + + let a: [u8; 100] = [0u8; 100]; + S::foo::<&[u8; 100]>(&a); + } + { + struct S; + + impl S { + fn foo>(&self, t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + } + + let a: [u8; 100] = [0u8; 100]; + S.foo::<&[u8; 100]>(&a); + } + // issue 10535 + { + static SOME_STATIC: String = String::new(); + + static UNIT: () = compute(&SOME_STATIC); + + pub const fn compute(_: T) + where + T: Copy, + { + } + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs new file mode 100644 index 0000000000000..f0567f486acca --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs @@ -0,0 +1,287 @@ +#![warn(clippy::needless_borrows_for_generic_args)] +#![allow( + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap, + clippy::needless_borrow +)] + +use core::ops::Deref; +use std::any::Any; +use std::ffi::OsStr; +use std::fmt::{Debug, Display}; +use std::path::Path; +use std::process::Command; + +fn main() { + let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + let _ = Path::new(".").join(&&"."); + let _ = Any::type_id(&""); // Don't lint. `Any` is only bound + let _ = Box::new(&""); // Don't lint. Type parameter appears in return type + let _ = Some("").unwrap_or(&""); + let _ = std::fs::write("x", &"".to_string()); + + { + #[derive(Clone, Copy)] + struct X; + + impl Deref for X { + type Target = X; + fn deref(&self) -> &Self::Target { + self + } + } + + fn deref_target_is_x>(_: T) {} + + deref_target_is_x(&X); + } + { + fn multiple_constraints(_: T) + where + T: IntoIterator + IntoIterator, + U: IntoIterator, + V: AsRef, + X: IntoIterator, + Y: AsRef, + { + } + + multiple_constraints(&[[""]]); + } + { + #[derive(Clone, Copy)] + struct X; + + impl Deref for X { + type Target = X; + fn deref(&self) -> &Self::Target { + self + } + } + + fn multiple_constraints_normalizes_to_same(_: T, _: V) + where + T: Deref, + U: Deref, + { + } + + multiple_constraints_normalizes_to_same(&X, X); + } + { + fn only_sized(_: T) {} + only_sized(&""); // Don't lint. `Sized` is only bound + } + { + fn ref_as_ref_path(_: &'static T) + where + &'static T: AsRef, + { + } + + ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter + } + { + trait RefsOnly { + type Referent; + } + + impl RefsOnly for &T { + type Referent = T; + } + + fn refs_only(_: T) + where + T: RefsOnly, + { + } + + refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't + } + { + fn multiple_constraints_normalizes_to_different(_: T, _: U) + where + T: IntoIterator, + U: IntoIterator, + V: AsRef, + { + } + multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments + } + // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 + { + #[derive(Clone, Copy)] + struct Iter; + impl Iterator for Iter { + type Item = (); + fn next(&mut self) -> Option { + None + } + } + fn takes_iter(_: impl Iterator) {} + fn dont_warn(mut x: Iter) { + takes_iter(&mut x); + } + #[allow(unused_mut)] + fn warn(mut x: &mut Iter) { + takes_iter(&mut x) + } + } + #[clippy::msrv = "1.52.0"] + { + let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + }; + #[clippy::msrv = "1.53.0"] + { + let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + }; + { + let env = "env".to_owned(); + let arg = "arg".to_owned(); + let f = |arg| { + let loc = "loc".to_owned(); + let _ = std::fs::write("x", &env); // Don't lint. In environment + let _ = std::fs::write("x", &arg); + let _ = std::fs::write("x", &loc); + }; + let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f` + f(arg); + } + { + #[derive(Debug)] + struct X; + + impl Drop for X { + fn drop(&mut self) {} + } + + fn f(_: impl Debug) {} + + let x = X; + f(&x); // Don't lint. Has significant drop + } + { + fn f(_: impl AsRef) {} + + let x = String::new(); + f(&x); + } + { + fn f(_: impl AsRef) {} + fn f2(_: impl AsRef) {} + + let x = String::new(); + f(&x); + f2(&x); + } + // https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 + // issue 9111 + { + struct A; + + impl Extend for A { + fn extend>(&mut self, _: T) { + unimplemented!() + } + } + + impl<'a> Extend<&'a u8> for A { + fn extend>(&mut self, _: T) { + unimplemented!() + } + } + + let mut a = A; + a.extend(&[]); // vs a.extend([]); + } + // issue 9710 + { + fn f(_: impl AsRef) {} + + let x = String::new(); + for _ in 0..10 { + f(&x); + } + } + // issue 9739 + { + fn foo(_it: impl IntoIterator) {} + foo(if std::env::var_os("HI").is_some() { + &[0] + } else { + &[] as &[u32] + }); + } + { + struct S; + + impl S { + fn foo(&self, _it: impl IntoIterator) {} + } + + S.foo(if std::env::var_os("HI").is_some() { + &[0] + } else { + &[] as &[u32] + }); + } + // issue 9782 + { + fn foo>(t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + + let a: [u8; 100] = [0u8; 100]; + + // 100 + foo::<[u8; 100]>(a); + foo(a); + + // 16 + foo::<&[u8]>(&a); + foo(a.as_slice()); + + // 8 + foo::<&[u8; 100]>(&a); + foo(&a); + } + { + struct S; + + impl S { + fn foo>(t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + } + + let a: [u8; 100] = [0u8; 100]; + S::foo::<&[u8; 100]>(&a); + } + { + struct S; + + impl S { + fn foo>(&self, t: T) { + println!("{}", std::mem::size_of::()); + let _t: &[u8] = t.as_ref(); + } + } + + let a: [u8; 100] = [0u8; 100]; + S.foo::<&[u8; 100]>(&a); + } + // issue 10535 + { + static SOME_STATIC: String = String::new(); + + static UNIT: () = compute(&SOME_STATIC); + + pub const fn compute(_: T) + where + T: Copy, + { + } + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr new file mode 100644 index 0000000000000..e2cde2c59a6e0 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr @@ -0,0 +1,77 @@ +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:16:37 + | +LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` + | + = note: `-D clippy::needless-borrows-for-generic-args` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:17:33 + | +LL | let _ = Path::new(".").join(&&"."); + | ^^^^^ help: change this to: `"."` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:21:33 + | +LL | let _ = std::fs::write("x", &"".to_string()); + | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:36:27 + | +LL | deref_target_is_x(&X); + | ^^ help: change this to: `X` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:49:30 + | +LL | multiple_constraints(&[[""]]); + | ^^^^^^^ help: change this to: `[[""]]` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:69:49 + | +LL | multiple_constraints_normalizes_to_same(&X, X); + | ^^ help: change this to: `X` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:127:24 + | +LL | takes_iter(&mut x) + | ^^^^^^ help: change this to: `x` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:136:41 + | +LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:144:41 + | +LL | let _ = std::fs::write("x", &arg); + | ^^^^ help: change this to: `arg` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:145:41 + | +LL | let _ = std::fs::write("x", &loc); + | ^^^^ help: change this to: `loc` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:167:11 + | +LL | f(&x); + | ^^ help: change this to: `x` + +error: the borrowed expression implements the required traits + --> $DIR/needless_borrows_for_generic_args.rs:247:13 + | +LL | foo(&a); + | ^^ help: change this to: `a` + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs index e1e5e8fd220b1..39d76f9990022 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs @@ -1,4 +1,5 @@ -#![allow(clippy::if_same_then_else, clippy::no_effect)] +#![allow(clippy::if_same_then_else, clippy::no_effect, clippy::redundant_closure_call)] +#![warn(clippy::needless_pass_by_ref_mut)] #![feature(lint_reasons)] //@no-rustfix use std::ptr::NonNull; @@ -230,6 +231,44 @@ async fn async_vec(b: &mut Vec) { async fn async_vec2(b: &mut Vec) { b.push(true); } +fn non_mut(n: &str) {} +//Should warn +pub async fn call_in_closure1(n: &mut str) { + (|| non_mut(n))() +} +fn str_mut(str: &mut String) -> bool { + str.pop().is_some() +} +//Should not warn +pub async fn call_in_closure2(str: &mut String) { + (|| str_mut(str))(); +} + +// Should not warn. +pub async fn closure(n: &mut usize) -> impl '_ + FnMut() { + || { + *n += 1; + } +} + +// Should warn. +pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { + //~^ ERROR: this argument is a mutable reference, but not used mutably + || *n + 1 +} + +// Should not warn. +pub async fn closure3(n: &mut usize) { + (|| *n += 1)(); +} + +// Should warn. +pub async fn closure4(n: &mut usize) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + (|| { + let _x = *n + 1; + })(); +} fn main() { let mut u = 0; diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr index df3df045776b8..aa937c3f6af2b 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,5 +1,5 @@ error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:6:11 + --> $DIR/needless_pass_by_ref_mut.rs:7:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:31:12 + --> $DIR/needless_pass_by_ref_mut.rs:32:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:44:29 + --> $DIR/needless_pass_by_ref_mut.rs:45:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:49:31 + --> $DIR/needless_pass_by_ref_mut.rs:50:31 | LL | fn badger(&mut self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:126:16 + --> $DIR/needless_pass_by_ref_mut.rs:127:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:130:16 + --> $DIR/needless_pass_by_ref_mut.rs:131:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:134:16 + --> $DIR/needless_pass_by_ref_mut.rs:135:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:138:16 + --> $DIR/needless_pass_by_ref_mut.rs:139:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:142:24 + --> $DIR/needless_pass_by_ref_mut.rs:143:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:146:24 + --> $DIR/needless_pass_by_ref_mut.rs:147:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:150:32 + --> $DIR/needless_pass_by_ref_mut.rs:151:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:154:24 + --> $DIR/needless_pass_by_ref_mut.rs:155:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:154:45 + --> $DIR/needless_pass_by_ref_mut.rs:155:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:188:16 + --> $DIR/needless_pass_by_ref_mut.rs:189:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:194:20 + --> $DIR/needless_pass_by_ref_mut.rs:195:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,16 +96,48 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:208:39 + --> $DIR/needless_pass_by_ref_mut.rs:209:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:216:26 + --> $DIR/needless_pass_by_ref_mut.rs:217:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` -error: aborting due to 17 previous errors +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:236:34 + | +LL | pub async fn call_in_closure1(n: &mut str) { + | ^^^^^^^^ help: consider changing to: `&str` + | + = warning: changing this function will impact semver compatibility + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:248:25 + | +LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() { + | ^^^^^^^^^^ help: consider changing to: `&usize` + | + = warning: changing this function will impact semver compatibility + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:255:20 + | +LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { + | ^^^^^^^^^^ help: consider changing to: `&usize` + | + = warning: changing this function will impact semver compatibility + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:266:26 + | +LL | pub async fn closure4(n: &mut usize) { + | ^^^^^^^^^^ help: consider changing to: `&usize` + | + = warning: changing this function will impact semver compatibility + +error: aborting due to 21 previous errors diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed index 855498105135e..4ea711fd67a14 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed @@ -18,4 +18,8 @@ fn main() { multiline string "; + + "no hashes"; + b"no hashes"; + c"no hashes"; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs index 06d4973038717..b6239f9b1f031 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string.rs @@ -18,4 +18,8 @@ fn main() { multiline string "#; + + r"no hashes"; + br"no hashes"; + cr"no hashes"; } diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr index e6806b31b1d96..276bc84c6c375 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr @@ -6,7 +6,7 @@ LL | r#"aaa"#; | = note: `-D clippy::needless-raw-strings` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]` -help: try +help: use a plain string literal instead | LL - r#"aaa"#; LL + "aaa"; @@ -18,7 +18,7 @@ error: unnecessary raw string literal LL | br#"aaa"#; | ^^^^^^^^^ | -help: try +help: use a plain byte string literal instead | LL - br#"aaa"#; LL + b"aaa"; @@ -30,7 +30,7 @@ error: unnecessary raw string literal LL | cr#"aaa"#; | ^^^^^^^^^ | -help: try +help: use a plain C string literal instead | LL - cr#"aaa"#; LL + c"aaa"; @@ -46,7 +46,7 @@ LL | | string LL | | "#; | |______^ | -help: try +help: use a plain string literal instead | LL ~ " LL | a @@ -55,5 +55,41 @@ LL | string LL ~ "; | -error: aborting due to 4 previous errors +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:22:5 + | +LL | r"no hashes"; + | ^^^^^^^^^^^^ + | +help: use a plain string literal instead + | +LL - r"no hashes"; +LL + "no hashes"; + | + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:23:5 + | +LL | br"no hashes"; + | ^^^^^^^^^^^^^ + | +help: use a plain byte string literal instead + | +LL - br"no hashes"; +LL + b"no hashes"; + | + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:24:5 + | +LL | cr"no hashes"; + | ^^^^^^^^^^^^^ + | +help: use a plain C string literal instead + | +LL - cr"no hashes"; +LL + c"no hashes"; + | + +error: aborting due to 7 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 e980adeeff4c1..c99c2f46532a3 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed @@ -21,4 +21,7 @@ fn main() { multiline string "; + + r"rust"; + r"hello world"; } 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 6113c5f25ae64..dcc2af69f4e9c 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs @@ -21,4 +21,7 @@ fn main() { multiline string "#; + + r###"rust"###; + r#"hello world"#; } 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 5a8e3d04543af..017160b1a421d 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr @@ -6,7 +6,7 @@ LL | r#"\aaa"#; | = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_raw_string_hashes)]` -help: remove all the hashes around the literal +help: remove all the hashes around the string literal | LL - r#"\aaa"#; LL + r"\aaa"; @@ -18,7 +18,7 @@ error: unnecessary hashes around raw string literal LL | r##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^ | -help: remove one hash from both sides of the literal +help: remove one hash from both sides of the string literal | LL - r##"Hello "world"!"##; LL + r#"Hello "world"!"#; @@ -30,7 +30,7 @@ error: unnecessary hashes around raw string literal LL | r######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 2 hashes from both sides of the literal +help: remove 2 hashes from both sides of the string literal | LL - r######" "### "## "# "######; LL + r####" "### "## "# "####; @@ -42,7 +42,7 @@ error: unnecessary hashes around raw string literal LL | r######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 3 hashes from both sides of the literal +help: remove 3 hashes from both sides of the string literal | LL - r######" "aa" "# "## "######; LL + r###" "aa" "# "## "###; @@ -54,7 +54,7 @@ error: unnecessary hashes around raw string literal LL | br#"\aaa"#; | ^^^^^^^^^^ | -help: remove all the hashes around the literal +help: remove all the hashes around the byte string literal | LL - br#"\aaa"#; LL + br"\aaa"; @@ -66,7 +66,7 @@ error: unnecessary hashes around raw string literal LL | br##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ | -help: remove one hash from both sides of the literal +help: remove one hash from both sides of the byte string literal | LL - br##"Hello "world"!"##; LL + br#"Hello "world"!"#; @@ -78,7 +78,7 @@ error: unnecessary hashes around raw string literal LL | br######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 2 hashes from both sides of the literal +help: remove 2 hashes from both sides of the byte string literal | LL - br######" "### "## "# "######; LL + br####" "### "## "# "####; @@ -90,7 +90,7 @@ error: unnecessary hashes around raw string literal LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 3 hashes from both sides of the literal +help: remove 3 hashes from both sides of the byte string literal | LL - br######" "aa" "# "## "######; LL + br###" "aa" "# "## "###; @@ -102,7 +102,7 @@ error: unnecessary hashes around raw string literal LL | cr#"\aaa"#; | ^^^^^^^^^^ | -help: remove all the hashes around the literal +help: remove all the hashes around the C string literal | LL - cr#"\aaa"#; LL + cr"\aaa"; @@ -114,7 +114,7 @@ error: unnecessary hashes around raw string literal LL | cr##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ | -help: remove one hash from both sides of the literal +help: remove one hash from both sides of the C string literal | LL - cr##"Hello "world"!"##; LL + cr#"Hello "world"!"#; @@ -126,7 +126,7 @@ error: unnecessary hashes around raw string literal LL | cr######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 2 hashes from both sides of the literal +help: remove 2 hashes from both sides of the C string literal | LL - cr######" "### "## "# "######; LL + cr####" "### "## "# "####; @@ -138,7 +138,7 @@ error: unnecessary hashes around raw string literal LL | cr######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: remove 3 hashes from both sides of the literal +help: remove 3 hashes from both sides of the C string literal | LL - cr######" "aa" "# "## "######; LL + cr###" "aa" "# "## "###; @@ -154,7 +154,7 @@ LL | | string LL | | "#; | |______^ | -help: remove all the hashes around the literal +help: remove all the hashes around the string literal | LL ~ r" LL | \a @@ -163,5 +163,29 @@ LL | string LL ~ "; | -error: aborting due to 13 previous errors +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:25:5 + | +LL | r###"rust"###; + | ^^^^^^^^^^^^^ + | +help: remove all the hashes around the string literal + | +LL - r###"rust"###; +LL + r"rust"; + | + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:26:5 + | +LL | r#"hello world"#; + | ^^^^^^^^^^^^^^^^ + | +help: remove all the hashes around the string literal + | +LL - r#"hello world"#; +LL + r"hello world"; + | + +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/no_effect_return.rs b/src/tools/clippy/tests/ui/no_effect_return.rs index f6585aa30a6f0..e46c0d73518b9 100644 --- a/src/tools/clippy/tests/ui/no_effect_return.rs +++ b/src/tools/clippy/tests/ui/no_effect_return.rs @@ -76,6 +76,7 @@ fn h() -> Vec { fn i() -> () { { + // does not suggest on function with explicit unit return type (); //~^ ERROR: statement with no effect } diff --git a/src/tools/clippy/tests/ui/no_effect_return.stderr b/src/tools/clippy/tests/ui/no_effect_return.stderr index b036e63420474..aed079f09b986 100644 --- a/src/tools/clippy/tests/ui/no_effect_return.stderr +++ b/src/tools/clippy/tests/ui/no_effect_return.stderr @@ -54,15 +54,13 @@ LL | ControlFlow::Break::<()>(()); | help: did you mean to return it?: `return` error: statement with no effect - --> $DIR/no_effect_return.rs:79:9 + --> $DIR/no_effect_return.rs:80:9 | LL | (); - | -^^ - | | - | help: did you mean to return it?: `return` + | ^^^ error: statement with no effect - --> $DIR/no_effect_return.rs:88:9 + --> $DIR/no_effect_return.rs:89:9 | LL | (); | ^^^ diff --git a/src/tools/clippy/tests/ui/option_filter_map.fixed b/src/tools/clippy/tests/ui/option_filter_map.fixed index d4c04ff907b2a..ee004c0e194bb 100644 --- a/src/tools/clippy/tests/ui/option_filter_map.fixed +++ b/src/tools/clippy/tests/ui/option_filter_map.fixed @@ -1,5 +1,5 @@ #![warn(clippy::option_filter_map)] -#![allow(clippy::map_flatten)] +#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] fn main() { let _ = Some(Some(1)).flatten(); diff --git a/src/tools/clippy/tests/ui/option_filter_map.rs b/src/tools/clippy/tests/ui/option_filter_map.rs index 99fb4723cab7a..eae2fa176a890 100644 --- a/src/tools/clippy/tests/ui/option_filter_map.rs +++ b/src/tools/clippy/tests/ui/option_filter_map.rs @@ -1,5 +1,5 @@ #![warn(clippy::option_filter_map)] -#![allow(clippy::map_flatten)] +#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] fn main() { let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); diff --git a/src/tools/clippy/tests/ui/path_ends_with_ext.fixed b/src/tools/clippy/tests/ui/path_ends_with_ext.fixed new file mode 100644 index 0000000000000..49767e242cee5 --- /dev/null +++ b/src/tools/clippy/tests/ui/path_ends_with_ext.fixed @@ -0,0 +1,36 @@ +#![warn(clippy::path_ends_with_ext)] +use std::path::Path; + +macro_rules! arg { + () => { + ".md" + }; +} + +fn test(path: &Path) { + path.extension().is_some_and(|ext| ext == "md"); + //~^ ERROR: this looks like a failed attempt at checking for the file extension + + // some "extensions" are allowed by default + path.ends_with(".git"); + + // most legitimate "dotfiles" are longer than 3 chars, so we allow them as well + path.ends_with(".bashrc"); + + // argument from expn shouldn't trigger + path.ends_with(arg!()); + + path.ends_with(".."); + path.ends_with("./a"); + path.ends_with("."); + path.ends_with(""); +} + +// is_some_and was stabilized in 1.70, so suggest map_or(false, ..) if under that +#[clippy::msrv = "1.69"] +fn under_msv(path: &Path) -> bool { + path.extension().map_or(false, |ext| ext == "md") + //~^ ERROR: this looks like a failed attempt at checking for the file extension +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/path_ends_with_ext.rs b/src/tools/clippy/tests/ui/path_ends_with_ext.rs new file mode 100644 index 0000000000000..2dfd046218afa --- /dev/null +++ b/src/tools/clippy/tests/ui/path_ends_with_ext.rs @@ -0,0 +1,36 @@ +#![warn(clippy::path_ends_with_ext)] +use std::path::Path; + +macro_rules! arg { + () => { + ".md" + }; +} + +fn test(path: &Path) { + path.ends_with(".md"); + //~^ ERROR: this looks like a failed attempt at checking for the file extension + + // some "extensions" are allowed by default + path.ends_with(".git"); + + // most legitimate "dotfiles" are longer than 3 chars, so we allow them as well + path.ends_with(".bashrc"); + + // argument from expn shouldn't trigger + path.ends_with(arg!()); + + path.ends_with(".."); + path.ends_with("./a"); + path.ends_with("."); + path.ends_with(""); +} + +// is_some_and was stabilized in 1.70, so suggest map_or(false, ..) if under that +#[clippy::msrv = "1.69"] +fn under_msv(path: &Path) -> bool { + path.ends_with(".md") + //~^ ERROR: this looks like a failed attempt at checking for the file extension +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/path_ends_with_ext.stderr b/src/tools/clippy/tests/ui/path_ends_with_ext.stderr new file mode 100644 index 0000000000000..a73ab4d08e9c5 --- /dev/null +++ b/src/tools/clippy/tests/ui/path_ends_with_ext.stderr @@ -0,0 +1,17 @@ +error: this looks like a failed attempt at checking for the file extension + --> $DIR/path_ends_with_ext.rs:11:5 + | +LL | path.ends_with(".md"); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `path.extension().is_some_and(|ext| ext == "md")` + | + = note: `-D clippy::path-ends-with-ext` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::path_ends_with_ext)]` + +error: this looks like a failed attempt at checking for the file extension + --> $DIR/path_ends_with_ext.rs:32:5 + | +LL | path.ends_with(".md") + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `path.extension().map_or(false, |ext| ext == "md")` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/print_literal.fixed b/src/tools/clippy/tests/ui/print_literal.fixed index 88cd3a54b4100..a7157c07f8a98 100644 --- a/src/tools/clippy/tests/ui/print_literal.fixed +++ b/src/tools/clippy/tests/ui/print_literal.fixed @@ -39,20 +39,30 @@ fn main() { // throw a warning println!("hello world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string println!("world hello"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // named args shouldn't change anything either println!("hello world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string println!("world hello"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // The string literal from `file!()` has a callsite span that isn't marked as coming from an // expansion println!("file: {}", file!()); + + // Braces in unicode escapes should not be escaped + println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}"); + println!("\\\u{1234}"); + // This does not lint because it would have to suggest unescaping the character + println!(r"{}", "\u{ab123}"); + // These are not unicode escapes + println!("\\u{{ab123}} \\u{{{{"); + println!(r"\u{{ab123}} \u{{{{"); + println!("\\{{ab123}} \\u{{{{"); + println!("\\u{{ab123}}"); + println!("\\\\u{{1234}}"); + + println!("mixed: {{hello}} {world}"); } diff --git a/src/tools/clippy/tests/ui/print_literal.rs b/src/tools/clippy/tests/ui/print_literal.rs index bd7444c9606ab..4b04b42744ccd 100644 --- a/src/tools/clippy/tests/ui/print_literal.rs +++ b/src/tools/clippy/tests/ui/print_literal.rs @@ -39,20 +39,30 @@ fn main() { // throw a warning println!("{0} {1}", "hello", "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string println!("{1} {0}", "hello", "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // named args shouldn't change anything either println!("{foo} {bar}", foo = "hello", bar = "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string println!("{bar} {foo}", foo = "hello", bar = "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // The string literal from `file!()` has a callsite span that isn't marked as coming from an // expansion println!("file: {}", file!()); + + // Braces in unicode escapes should not be escaped + println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}"); + println!("{}", "\\\u{1234}"); + // This does not lint because it would have to suggest unescaping the character + println!(r"{}", "\u{ab123}"); + // These are not unicode escapes + println!("{}", r"\u{ab123} \u{{"); + println!(r"{}", r"\u{ab123} \u{{"); + println!("{}", r"\{ab123} \u{{"); + println!("{}", "\\u{ab123}"); + println!("{}", "\\\\u{1234}"); + + println!("mixed: {} {world}", "{hello}"); } diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr index 1d9751b92e9c5..8c011d7bc0a6f 100644 --- a/src/tools/clippy/tests/ui/print_literal.stderr +++ b/src/tools/clippy/tests/ui/print_literal.stderr @@ -52,97 +52,145 @@ error: literal with an empty format string --> $DIR/print_literal.rs:40:25 | LL | println!("{0} {1}", "hello", "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^^^^ | help: try | LL - println!("{0} {1}", "hello", "world"); -LL + println!("hello {1}", "world"); +LL + println!("hello world"); | error: literal with an empty format string - --> $DIR/print_literal.rs:40:34 + --> $DIR/print_literal.rs:42:25 | -LL | println!("{0} {1}", "hello", "world"); - | ^^^^^^^ +LL | println!("{1} {0}", "hello", "world"); + | ^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{0} {1}", "hello", "world"); -LL + println!("{0} world", "hello"); +LL - println!("{1} {0}", "hello", "world"); +LL + println!("world hello"); | error: literal with an empty format string - --> $DIR/print_literal.rs:43:34 + --> $DIR/print_literal.rs:46:35 | -LL | println!("{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | println!("{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{1} {0}", "hello", "world"); -LL + println!("world {0}", "hello"); +LL - println!("{foo} {bar}", foo = "hello", bar = "world"); +LL + println!("hello world"); | error: literal with an empty format string - --> $DIR/print_literal.rs:43:25 + --> $DIR/print_literal.rs:48:35 | -LL | println!("{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | println!("{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{1} {0}", "hello", "world"); -LL + println!("{1} hello", "world"); +LL - println!("{bar} {foo}", foo = "hello", bar = "world"); +LL + println!("world hello"); | error: literal with an empty format string - --> $DIR/print_literal.rs:48:35 + --> $DIR/print_literal.rs:56:20 | -LL | println!("{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{foo} {bar}", foo = "hello", bar = "world"); -LL + println!("hello {bar}", bar = "world"); +LL - println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}"); +LL + println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}"); | error: literal with an empty format string - --> $DIR/print_literal.rs:48:50 + --> $DIR/print_literal.rs:57:20 | -LL | println!("{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | println!("{}", "\\\u{1234}"); + | ^^^^^^^^^^^^ | help: try | -LL - println!("{foo} {bar}", foo = "hello", bar = "world"); -LL + println!("{foo} world", foo = "hello"); +LL - println!("{}", "\\\u{1234}"); +LL + println!("\\\u{1234}"); | error: literal with an empty format string - --> $DIR/print_literal.rs:51:50 + --> $DIR/print_literal.rs:61:20 | -LL | println!("{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | println!("{}", r"\u{ab123} \u{{"); + | ^^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{bar} {foo}", foo = "hello", bar = "world"); -LL + println!("world {foo}", foo = "hello"); +LL - println!("{}", r"\u{ab123} \u{{"); +LL + println!("\\u{{ab123}} \\u{{{{"); | error: literal with an empty format string - --> $DIR/print_literal.rs:51:35 + --> $DIR/print_literal.rs:62:21 | -LL | println!("{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | println!(r"{}", r"\u{ab123} \u{{"); + | ^^^^^^^^^^^^^^^^^ | help: try | -LL - println!("{bar} {foo}", foo = "hello", bar = "world"); -LL + println!("{bar} hello", bar = "world"); +LL - println!(r"{}", r"\u{ab123} \u{{"); +LL + println!(r"\u{{ab123}} \u{{{{"); + | + +error: literal with an empty format string + --> $DIR/print_literal.rs:63:20 + | +LL | println!("{}", r"\{ab123} \u{{"); + | ^^^^^^^^^^^^^^^^ + | +help: try + | +LL - println!("{}", r"\{ab123} \u{{"); +LL + println!("\\{{ab123}} \\u{{{{"); + | + +error: literal with an empty format string + --> $DIR/print_literal.rs:64:20 + | +LL | println!("{}", "\\u{ab123}"); + | ^^^^^^^^^^^^ + | +help: try + | +LL - println!("{}", "\\u{ab123}"); +LL + println!("\\u{{ab123}}"); + | + +error: literal with an empty format string + --> $DIR/print_literal.rs:65:20 + | +LL | println!("{}", "\\\\u{1234}"); + | ^^^^^^^^^^^^^ + | +help: try + | +LL - println!("{}", "\\\\u{1234}"); +LL + println!("\\\\u{{1234}}"); + | + +error: literal with an empty format string + --> $DIR/print_literal.rs:67:35 + | +LL | println!("mixed: {} {world}", "{hello}"); + | ^^^^^^^^^ + | +help: try + | +LL - println!("mixed: {} {world}", "{hello}"); +LL + println!("mixed: {{hello}} {world}"); | -error: aborting due to 12 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_allocation.rs b/src/tools/clippy/tests/ui/redundant_allocation.rs index b3257c04f8296..e70f8e71fae85 100644 --- a/src/tools/clippy/tests/ui/redundant_allocation.rs +++ b/src/tools/clippy/tests/ui/redundant_allocation.rs @@ -159,4 +159,9 @@ mod box_fat_ptr { //~| NOTE: `Box>` is already on the heap, `Rc>>` makes } +// https://github.com/rust-lang/rust-clippy/issues/11417 +fn type_in_closure() { + let _ = |_: &mut Box>| {}; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/redundant_as_str.fixed b/src/tools/clippy/tests/ui/redundant_as_str.fixed new file mode 100644 index 0000000000000..a38523a7c79e7 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_as_str.fixed @@ -0,0 +1,24 @@ +#![warn(clippy::redundant_as_str)] + +fn main() { + let string = "Hello, world!".to_owned(); + + // These methods are redundant and the `as_str` can be removed + let _redundant = string.as_bytes(); + let _redundant = string.is_empty(); + + // These methods don't use `as_str` when they are redundant + let _no_as_str = string.as_bytes(); + let _no_as_str = string.is_empty(); + + // These methods are not redundant, and are equivelant to + // doing dereferencing the string and applying the method + let _not_redundant = string.as_str().escape_unicode(); + let _not_redundant = string.as_str().trim(); + let _not_redundant = string.as_str().split_whitespace(); + + // These methods don't use `as_str` and are applied on a `str` directly + let borrowed_str = "Hello, world!"; + let _is_str = borrowed_str.as_bytes(); + let _is_str = borrowed_str.is_empty(); +} diff --git a/src/tools/clippy/tests/ui/redundant_as_str.rs b/src/tools/clippy/tests/ui/redundant_as_str.rs new file mode 100644 index 0000000000000..33adb60999641 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_as_str.rs @@ -0,0 +1,24 @@ +#![warn(clippy::redundant_as_str)] + +fn main() { + let string = "Hello, world!".to_owned(); + + // These methods are redundant and the `as_str` can be removed + let _redundant = string.as_str().as_bytes(); + let _redundant = string.as_str().is_empty(); + + // These methods don't use `as_str` when they are redundant + let _no_as_str = string.as_bytes(); + let _no_as_str = string.is_empty(); + + // These methods are not redundant, and are equivelant to + // doing dereferencing the string and applying the method + let _not_redundant = string.as_str().escape_unicode(); + let _not_redundant = string.as_str().trim(); + let _not_redundant = string.as_str().split_whitespace(); + + // These methods don't use `as_str` and are applied on a `str` directly + let borrowed_str = "Hello, world!"; + let _is_str = borrowed_str.as_bytes(); + let _is_str = borrowed_str.is_empty(); +} diff --git a/src/tools/clippy/tests/ui/redundant_as_str.stderr b/src/tools/clippy/tests/ui/redundant_as_str.stderr new file mode 100644 index 0000000000000..0ea42a94a81ed --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_as_str.stderr @@ -0,0 +1,17 @@ +error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too + --> $DIR/redundant_as_str.rs:7:29 + | +LL | let _redundant = string.as_str().as_bytes(); + | ^^^^^^^^^^^^^^^^^ help: try: `as_bytes` + | + = note: `-D clippy::redundant-as-str` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::redundant_as_str)]` + +error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too + --> $DIR/redundant_as_str.rs:8:29 + | +LL | let _redundant = string.as_str().is_empty(); + | ^^^^^^^^^^^^^^^^^ help: try: `is_empty` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed index bbe3b38e547bb..c578e786426f8 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.fixed +++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed @@ -1,8 +1,9 @@ +//@aux-build:proc_macros.rs #![warn(clippy::redundant_field_names)] #![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)] #[macro_use] -extern crate derive_new; +extern crate proc_macros; use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; @@ -18,7 +19,6 @@ struct Person { foo: u8, } -#[derive(new)] pub struct S { v: String, } @@ -57,6 +57,13 @@ fn main() { let _ = Range { start, end }; let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end }; + + external! { + let v = String::new(); + let _ = S { + v: v + }; + } } fn issue_3476() { diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs index 9afa191ce7c70..d8c2286d5ad65 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.rs +++ b/src/tools/clippy/tests/ui/redundant_field_names.rs @@ -1,8 +1,9 @@ +//@aux-build:proc_macros.rs #![warn(clippy::redundant_field_names)] #![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)] #[macro_use] -extern crate derive_new; +extern crate proc_macros; use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; @@ -18,7 +19,6 @@ struct Person { foo: u8, } -#[derive(new)] pub struct S { v: String, } @@ -57,6 +57,13 @@ fn main() { let _ = Range { start: start, end: end }; let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end: end }; + + external! { + let v = String::new(); + let _ = S { + v: v + }; + } } fn issue_3476() { diff --git a/src/tools/clippy/tests/ui/redundant_field_names.stderr b/src/tools/clippy/tests/ui/redundant_field_names.stderr index 5fee60b8ea411..6eb1cc7531928 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.stderr +++ b/src/tools/clippy/tests/ui/redundant_field_names.stderr @@ -44,7 +44,7 @@ LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:81:25 + --> $DIR/redundant_field_names.rs:88:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed index 9a1ec3a4d36a6..f23116a7e1c5c 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.fixed +++ b/src/tools/clippy/tests/ui/redundant_guards.fixed @@ -43,6 +43,7 @@ fn main() { }, Some(Some(1)) => .., Some(Some(2)) => .., + Some(Some(2)) => .., // Don't lint, since x is used in the body Some(x) if let Some(1) = x => { x; @@ -56,11 +57,13 @@ fn main() { Some(x) if matches!(y, 1 if true) => .., Some(x) if let 1 = y => .., Some(x) if y == 2 => .., + Some(x) if 2 == y => .., _ => todo!(), }; let a = A(1); match a { _ if a.0 == 1 => {}, + _ if 1 == a.0 => {}, _ => todo!(), } let b = B { e: Some(A(0)) }; @@ -119,6 +122,7 @@ fn h(v: Option) { fn f(s: Option) { match s { Some(x) if x == "a" => {}, + Some(x) if "a" == x => {}, _ => {}, } } @@ -140,6 +144,52 @@ static CONST_S: S = S { a: 1 }; fn g(opt_s: Option) { match opt_s { Some(x) if x == CONST_S => {}, + Some(x) if CONST_S == x => {}, _ => {}, } } + +mod issue11465 { + enum A { + Foo([u8; 3]), + } + + struct B { + b: String, + c: i32, + } + + fn issue11465() { + let c = Some(1); + match c { + Some(1) => {}, + Some(1) => {}, + Some(2) => {}, + Some(3) => {}, + _ => {}, + }; + + let enum_a = A::Foo([98, 97, 114]); + match enum_a { + A::Foo(ref arr) if arr == b"foo" => {}, + A::Foo(ref arr) if b"foo" == arr => {}, + A::Foo(ref arr) if let b"bar" = arr => {}, + A::Foo(ref arr) if matches!(arr, b"baz") => {}, + _ => {}, + }; + + let struct_b = B { + b: "bar".to_string(), + c: 42, + }; + match struct_b { + B { ref b, .. } if b == "bar" => {}, + B { ref b, .. } if "bar" == b => {}, + B { c: 1, .. } => {}, + B { c: 1, .. } => {}, + B { c: 1, .. } => {}, + B { c: 1, .. } => {}, + _ => {}, + } + } +} diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs index e2e0ee816c51b..c0206b4cec75f 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.rs +++ b/src/tools/clippy/tests/ui/redundant_guards.rs @@ -43,6 +43,7 @@ fn main() { }, Some(x) if let Some(1) = x => .., Some(x) if x == Some(2) => .., + Some(x) if Some(2) == x => .., // Don't lint, since x is used in the body Some(x) if let Some(1) = x => { x; @@ -56,11 +57,13 @@ fn main() { Some(x) if matches!(y, 1 if true) => .., Some(x) if let 1 = y => .., Some(x) if y == 2 => .., + Some(x) if 2 == y => .., _ => todo!(), }; let a = A(1); match a { _ if a.0 == 1 => {}, + _ if 1 == a.0 => {}, _ => todo!(), } let b = B { e: Some(A(0)) }; @@ -119,6 +122,7 @@ fn h(v: Option) { fn f(s: Option) { match s { Some(x) if x == "a" => {}, + Some(x) if "a" == x => {}, _ => {}, } } @@ -140,6 +144,52 @@ static CONST_S: S = S { a: 1 }; fn g(opt_s: Option) { match opt_s { Some(x) if x == CONST_S => {}, + Some(x) if CONST_S == x => {}, _ => {}, } } + +mod issue11465 { + enum A { + Foo([u8; 3]), + } + + struct B { + b: String, + c: i32, + } + + fn issue11465() { + let c = Some(1); + match c { + Some(ref x) if x == &1 => {}, + Some(ref x) if &1 == x => {}, + Some(ref x) if let &2 = x => {}, + Some(ref x) if matches!(x, &3) => {}, + _ => {}, + }; + + let enum_a = A::Foo([98, 97, 114]); + match enum_a { + A::Foo(ref arr) if arr == b"foo" => {}, + A::Foo(ref arr) if b"foo" == arr => {}, + A::Foo(ref arr) if let b"bar" = arr => {}, + A::Foo(ref arr) if matches!(arr, b"baz") => {}, + _ => {}, + }; + + let struct_b = B { + b: "bar".to_string(), + c: 42, + }; + match struct_b { + B { ref b, .. } if b == "bar" => {}, + B { ref b, .. } if "bar" == b => {}, + B { ref c, .. } if c == &1 => {}, + B { ref c, .. } if &1 == c => {}, + B { ref c, .. } if let &1 = c => {}, + B { ref c, .. } if matches!(c, &1) => {}, + _ => {}, + } + } +} diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr index 0a45a6d7619fe..b8d7834e358ca 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.stderr +++ b/src/tools/clippy/tests/ui/redundant_guards.stderr @@ -60,7 +60,19 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> $DIR/redundant_guards.rs:68:20 + --> $DIR/redundant_guards.rs:46:20 + | +LL | Some(x) if Some(2) == x => .., + | ^^^^^^^^^^^^ + | +help: try + | +LL - Some(x) if Some(2) == x => .., +LL + Some(Some(2)) => .., + | + +error: redundant guard + --> $DIR/redundant_guards.rs:71:20 | LL | B { e } if matches!(e, Some(A(2))) => .., | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +84,7 @@ LL + B { e: Some(A(2)) } => .., | error: redundant guard - --> $DIR/redundant_guards.rs:105:20 + --> $DIR/redundant_guards.rs:108:20 | LL | E::A(y) if y == "not from an or pattern" => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +96,7 @@ LL + E::A("not from an or pattern") => {}, | error: redundant guard - --> $DIR/redundant_guards.rs:112:14 + --> $DIR/redundant_guards.rs:115:14 | LL | x if matches!(x, Some(0)) => .., | ^^^^^^^^^^^^^^^^^^^^ @@ -95,5 +107,101 @@ LL - x if matches!(x, Some(0)) => .., LL + Some(0) => .., | -error: aborting due to 8 previous errors +error: redundant guard + --> $DIR/redundant_guards.rs:165:28 + | +LL | Some(ref x) if x == &1 => {}, + | ^^^^^^^ + | +help: try + | +LL - Some(ref x) if x == &1 => {}, +LL + Some(1) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:166:28 + | +LL | Some(ref x) if &1 == x => {}, + | ^^^^^^^ + | +help: try + | +LL - Some(ref x) if &1 == x => {}, +LL + Some(1) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:167:28 + | +LL | Some(ref x) if let &2 = x => {}, + | ^^^^^^^^^^ + | +help: try + | +LL - Some(ref x) if let &2 = x => {}, +LL + Some(2) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:168:28 + | +LL | Some(ref x) if matches!(x, &3) => {}, + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL - Some(ref x) if matches!(x, &3) => {}, +LL + Some(3) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:188:32 + | +LL | B { ref c, .. } if c == &1 => {}, + | ^^^^^^^ + | +help: try + | +LL - B { ref c, .. } if c == &1 => {}, +LL + B { c: 1, .. } => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:189:32 + | +LL | B { ref c, .. } if &1 == c => {}, + | ^^^^^^^ + | +help: try + | +LL - B { ref c, .. } if &1 == c => {}, +LL + B { c: 1, .. } => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:190:32 + | +LL | B { ref c, .. } if let &1 = c => {}, + | ^^^^^^^^^^ + | +help: try + | +LL - B { ref c, .. } if let &1 = c => {}, +LL + B { c: 1, .. } => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:191:32 + | +LL | B { ref c, .. } if matches!(c, &1) => {}, + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL - B { ref c, .. } if matches!(c, &1) => {}, +LL + B { c: 1, .. } => {}, + | + +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs index c5d93e4365d90..e81db300f15a2 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.rs +++ b/src/tools/clippy/tests/ui/redundant_locals.rs @@ -118,3 +118,40 @@ fn macros() { let x = x; } } + +struct WithDrop(usize); +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +struct InnerDrop(WithDrop); + +struct ComposeDrop { + d: WithDrop, +} + +struct WithoutDrop(usize); + +fn drop_trait() { + let a = WithDrop(1); + let b = WithDrop(2); + let a = a; +} + +fn without_drop() { + let a = WithoutDrop(1); + let b = WithoutDrop(2); + let a = a; +} + +fn drop_inner() { + let a = InnerDrop(WithDrop(1)); + let b = InnerDrop(WithDrop(2)); + let a = a; +} + +fn drop_compose() { + let a = ComposeDrop { d: WithDrop(1) }; + let b = ComposeDrop { d: WithDrop(1) }; + let a = a; +} diff --git a/src/tools/clippy/tests/ui/redundant_locals.stderr b/src/tools/clippy/tests/ui/redundant_locals.stderr index 13b872e9576d8..d794a87fe7df6 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.stderr +++ b/src/tools/clippy/tests/ui/redundant_locals.stderr @@ -1,137 +1,172 @@ -error: redundant redefinition of a binding - --> $DIR/redundant_locals.rs:11:9 +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:12:5 | -LL | let x = 1; - | ^ LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` +help: `x` is initially defined here + --> $DIR/redundant_locals.rs:11:9 + | +LL | let x = 1; + | ^ = note: `-D clippy::redundant-locals` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::redundant_locals)]` -error: redundant redefinition of a binding - --> $DIR/redundant_locals.rs:16:9 +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:17:5 | -LL | let mut x = 1; - | ^^^^^ LL | let mut x = x; | ^^^^^^^^^^^^^^ | - = help: remove the redefinition of `x` +help: `x` is initially defined here + --> $DIR/redundant_locals.rs:16:9 + | +LL | let mut x = 1; + | ^^^^^ -error: redundant redefinition of a binding +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:47:5 + | +LL | let x = x; + | ^^^^^^^^^^ + | +help: `x` is initially defined here --> $DIR/redundant_locals.rs:46:14 | LL | fn parameter(x: i32) { | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:52:5 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:51:9 | LL | let x = 1; | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:53:5 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:52:9 | LL | let x = x; | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:54:5 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:53:9 | LL | let x = x; | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:55:5 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:54:9 | LL | let x = x; | ^ -LL | let x = x; + +error: redundant redefinition of a binding `a` + --> $DIR/redundant_locals.rs:61:5 + | +LL | let a = a; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `a` is initially defined here --> $DIR/redundant_locals.rs:59:9 | LL | let a = 1; | ^ -LL | let b = 2; -LL | let a = a; + +error: redundant redefinition of a binding `b` + --> $DIR/redundant_locals.rs:62:5 + | +LL | let b = b; | ^^^^^^^^^^ | - = help: remove the redefinition of `a` - -error: redundant redefinition of a binding +help: `b` is initially defined here --> $DIR/redundant_locals.rs:60:9 | LL | let b = 2; | ^ -LL | let a = a; -LL | let b = b; - | ^^^^^^^^^^ - | - = help: remove the redefinition of `b` -error: redundant redefinition of a binding +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:68:9 + | +LL | let x = x; + | ^^^^^^^^^^ + | +help: `x` is initially defined here --> $DIR/redundant_locals.rs:67:13 | LL | let x = 1; | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:75:9 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:74:13 | LL | let x = 1; | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:78:9 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:77:6 | LL | |x: i32| { | ^ + +error: redundant redefinition of a binding `x` + --> $DIR/redundant_locals.rs:97:9 + | LL | let x = x; | ^^^^^^^^^^ | - = help: remove the redefinition of `x` - -error: redundant redefinition of a binding +help: `x` is initially defined here --> $DIR/redundant_locals.rs:94:9 | LL | let x = 1; | ^ -... -LL | let x = x; - | ^^^^^^^^^^ + +error: redundant redefinition of a binding `a` + --> $DIR/redundant_locals.rs:144:5 + | +LL | let a = a; + | ^^^^^^^^^^ | - = help: remove the redefinition of `x` +help: `a` is initially defined here + --> $DIR/redundant_locals.rs:142:9 + | +LL | let a = WithoutDrop(1); + | ^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs index 5259d9ce04bbf..094d9574ae987 100644 --- a/src/tools/clippy/tests/ui/regex.rs +++ b/src/tools/clippy/tests/ui/regex.rs @@ -2,7 +2,8 @@ unused, clippy::needless_raw_strings, clippy::needless_raw_string_hashes, - clippy::needless_borrow + clippy::needless_borrow, + clippy::needless_borrows_for_generic_args )] #![warn(clippy::invalid_regex, clippy::trivial_regex)] diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr index 91f90157e6847..6d98d691d6f0a 100644 --- a/src/tools/clippy/tests/ui/regex.stderr +++ b/src/tools/clippy/tests/ui/regex.stderr @@ -1,5 +1,5 @@ error: trivial regex - --> $DIR/regex.rs:18:45 + --> $DIR/regex.rs:19:45 | LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ @@ -9,7 +9,7 @@ LL | let pipe_in_wrong_position = Regex::new("|"); = help: to override `-D warnings` add `#[allow(clippy::trivial_regex)]` error: trivial regex - --> $DIR/regex.rs:20:60 + --> $DIR/regex.rs:21:60 | LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ @@ -17,7 +17,7 @@ LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:22:42 + --> $DIR/regex.rs:23:42 | LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ @@ -26,7 +26,7 @@ LL | let wrong_char_ranice = Regex::new("[z-a]"); = help: to override `-D warnings` add `#[allow(clippy::invalid_regex)]` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:25:37 + --> $DIR/regex.rs:26:37 | LL | let some_unicode = Regex::new("[é-è]"); | ^^^ @@ -35,13 +35,13 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:28:33 + --> $DIR/regex.rs:29:33 | LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:30:53 + --> $DIR/regex.rs:31:53 | LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ @@ -52,7 +52,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:32:41 + --> $DIR/regex.rs:33:41 | LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:33:56 + --> $DIR/regex.rs:34:56 | LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:45:37 + --> $DIR/regex.rs:46:37 | LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:46:39 + --> $DIR/regex.rs:47:39 | LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ error: regex parse error: \b\c ^^ error: unrecognized escape sequence - --> $DIR/regex.rs:53:42 + --> $DIR/regex.rs:54:42 | LL | let escaped_string_span = Regex::new("\\b\\c"); | ^^^^^^^^ @@ -96,19 +96,19 @@ LL | let escaped_string_span = Regex::new("\\b\\c"); = help: consider using a raw string literal: `r".."` error: regex syntax error: duplicate flag - --> $DIR/regex.rs:55:34 + --> $DIR/regex.rs:56:34 | LL | let aux_span = Regex::new("(?ixi)"); | ^ ^ error: regex syntax error: pattern can match invalid UTF-8 - --> $DIR/regex.rs:61:53 + --> $DIR/regex.rs:62:53 | LL | let invalid_utf8_should_lint = Regex::new("(?-u)."); | ^ error: trivial regex - --> $DIR/regex.rs:66:33 + --> $DIR/regex.rs:67:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:69:48 + --> $DIR/regex.rs:70:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:72:42 + --> $DIR/regex.rs:73:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -132,7 +132,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:75:40 + --> $DIR/regex.rs:76:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -140,7 +140,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:78:39 + --> $DIR/regex.rs:79:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -148,7 +148,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:81:39 + --> $DIR/regex.rs:82:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:84:40 + --> $DIR/regex.rs:85:40 | LL | let trivial_backslash = Regex::new("a\\.b"); | ^^^^^^^ @@ -164,7 +164,7 @@ LL | let trivial_backslash = Regex::new("a\\.b"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:88:36 + --> $DIR/regex.rs:89:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -172,7 +172,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:91:36 + --> $DIR/regex.rs:92:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -180,7 +180,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:94:36 + --> $DIR/regex.rs:95:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -188,7 +188,7 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:97:44 + --> $DIR/regex.rs:98:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.rs b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.rs index a4dfc8f293d3f..62798b6d3d6f3 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.rs +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.rs @@ -1,6 +1,6 @@ #![warn(clippy::result_map_unit_fn)] #![feature(never_type)] -#![allow(unused)] +#![allow(unused, clippy::unnecessary_map_on_constructor)] //@no-rustfix struct HasResult { field: Result, diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs index 550ec00726817..33211b32d74b3 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs @@ -40,8 +40,6 @@ impl T { pub fn hash(&self, state: &mut T) { //~^ ERROR: method `hash` can be confused for the standard trait method `std::hash::Ha - //~| ERROR: this argument is a mutable reference, but not used mutably - //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` unimplemented!() } diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr index 79afddea24798..c257f41134266 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr @@ -38,8 +38,6 @@ error: method `hash` can be confused for the standard trait method `std::hash::H | LL | / pub fn hash(&self, state: &mut T) { LL | | -LL | | -LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -47,7 +45,7 @@ LL | | } = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name error: method `index` can be confused for the standard trait method `std::ops::Index::index` - --> $DIR/method_list_2.rs:48:5 + --> $DIR/method_list_2.rs:46:5 | LL | / pub fn index(&self, index: usize) -> &Self { LL | | @@ -58,7 +56,7 @@ LL | | } = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` - --> $DIR/method_list_2.rs:53:5 + --> $DIR/method_list_2.rs:51:5 | LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { LL | | @@ -69,7 +67,7 @@ LL | | } = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` - --> $DIR/method_list_2.rs:58:5 + --> $DIR/method_list_2.rs:56:5 | LL | / pub fn into_iter(self) -> Self { LL | | @@ -80,7 +78,7 @@ LL | | } = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` - --> $DIR/method_list_2.rs:63:5 + --> $DIR/method_list_2.rs:61:5 | LL | / pub fn mul(self, rhs: Self) -> Self { LL | | @@ -91,7 +89,7 @@ LL | | } = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` - --> $DIR/method_list_2.rs:68:5 + --> $DIR/method_list_2.rs:66:5 | LL | / pub fn neg(self) -> Self { LL | | @@ -102,7 +100,7 @@ LL | | } = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` - --> $DIR/method_list_2.rs:73:5 + --> $DIR/method_list_2.rs:71:5 | LL | / pub fn next(&mut self) -> Option { LL | | @@ -113,7 +111,7 @@ LL | | } = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name error: method `not` can be confused for the standard trait method `std::ops::Not::not` - --> $DIR/method_list_2.rs:78:5 + --> $DIR/method_list_2.rs:76:5 | LL | / pub fn not(self) -> Self { LL | | @@ -124,7 +122,7 @@ LL | | } = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` - --> $DIR/method_list_2.rs:83:5 + --> $DIR/method_list_2.rs:81:5 | LL | / pub fn rem(self, rhs: Self) -> Self { LL | | @@ -135,7 +133,7 @@ LL | | } = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` - --> $DIR/method_list_2.rs:88:5 + --> $DIR/method_list_2.rs:86:5 | LL | / pub fn shl(self, rhs: Self) -> Self { LL | | @@ -146,7 +144,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` - --> $DIR/method_list_2.rs:93:5 + --> $DIR/method_list_2.rs:91:5 | LL | / pub fn shr(self, rhs: Self) -> Self { LL | | @@ -157,7 +155,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` - --> $DIR/method_list_2.rs:98:5 + --> $DIR/method_list_2.rs:96:5 | LL | / pub fn sub(self, rhs: Self) -> Self { LL | | @@ -167,15 +165,5 @@ LL | | } | = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name -error: this argument is a mutable reference, but not used mutably - --> $DIR/method_list_2.rs:41:31 - | -LL | pub fn hash(&self, state: &mut T) { - | ^^^^^^ help: consider changing to: `&T` - | - = warning: changing this function will impact semver compatibility - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.rs b/src/tools/clippy/tests/ui/slow_vector_initialization.rs index 5c3086c9d69ea..16f81019574fb 100644 --- a/src/tools/clippy/tests/ui/slow_vector_initialization.rs +++ b/src/tools/clippy/tests/ui/slow_vector_initialization.rs @@ -103,8 +103,6 @@ fn from_empty_vec() { } fn do_stuff(vec: &mut [u8]) {} -//~^ ERROR: this argument is a mutable reference, but not used mutably -//~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` fn extend_vector_with_manipulations_between() { let len = 300; diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr index 4d24400ecb596..16a7057653c10 100644 --- a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr +++ b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr @@ -105,14 +105,5 @@ LL | vec1 = vec![]; LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/slow_vector_initialization.rs:105:18 - | -LL | fn do_stuff(vec: &mut [u8]) {} - | ^^^^^^^^^ help: consider changing to: `&[u8]` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` - -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed index 8027c053fb5b0..a7555704fbe01 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed +++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed @@ -1,8 +1,12 @@ +//@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] #![allow(unused_imports)] extern crate alloc; +#[macro_use] +extern crate proc_macro_derive; + #[warn(clippy::std_instead_of_core)] fn std_instead_of_core() { // Regular import @@ -55,6 +59,13 @@ fn alloc_instead_of_core() { //~^ ERROR: used import from `alloc` instead of `core` } +mod std_in_proc_macro_derive { + #[warn(clippy::alloc_instead_of_core)] + #[allow(unused)] + #[derive(ImplStructWithStdDisplay)] + struct B {} +} + fn main() { std_instead_of_core(); std_instead_of_alloc(); diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs index 63a096384d716..af7f3399f4923 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.rs +++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs @@ -1,8 +1,12 @@ +//@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] #![allow(unused_imports)] extern crate alloc; +#[macro_use] +extern crate proc_macro_derive; + #[warn(clippy::std_instead_of_core)] fn std_instead_of_core() { // Regular import @@ -55,6 +59,13 @@ fn alloc_instead_of_core() { //~^ ERROR: used import from `alloc` instead of `core` } +mod std_in_proc_macro_derive { + #[warn(clippy::alloc_instead_of_core)] + #[allow(unused)] + #[derive(ImplStructWithStdDisplay)] + struct B {} +} + fn main() { std_instead_of_core(); std_instead_of_alloc(); diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr index ca26f77bd37f9..4f7bdc4045e77 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr +++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:9:9 + --> $DIR/std_instead_of_core.rs:13:9 | LL | use std::hash::Hasher; | ^^^ help: consider importing the item from `core`: `core` @@ -8,49 +8,49 @@ LL | use std::hash::Hasher; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:12:11 + --> $DIR/std_instead_of_core.rs:16:11 | LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:18:9 + --> $DIR/std_instead_of_core.rs:22:9 | LL | use std::fmt::{Debug, Result}; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:22:15 + --> $DIR/std_instead_of_core.rs:26:15 | LL | let ptr = std::ptr::null::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:24:21 + --> $DIR/std_instead_of_core.rs:28:21 | LL | let ptr_mut = ::std::ptr::null_mut::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:28:16 + --> $DIR/std_instead_of_core.rs:32:16 | LL | let cell = std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:30:27 + --> $DIR/std_instead_of_core.rs:34:27 | LL | let cell_absolute = ::std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> $DIR/std_instead_of_core.rs:39:9 + --> $DIR/std_instead_of_core.rs:43:9 | LL | use std::iter::Iterator; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `alloc` - --> $DIR/std_instead_of_core.rs:46:9 + --> $DIR/std_instead_of_core.rs:50:9 | LL | use std::vec; | ^^^ help: consider importing the item from `alloc`: `alloc` @@ -59,13 +59,13 @@ LL | use std::vec; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` error: used import from `std` instead of `alloc` - --> $DIR/std_instead_of_core.rs:48:9 + --> $DIR/std_instead_of_core.rs:52:9 | LL | use std::vec::Vec; | ^^^ help: consider importing the item from `alloc`: `alloc` error: used import from `alloc` instead of `core` - --> $DIR/std_instead_of_core.rs:54:9 + --> $DIR/std_instead_of_core.rs:58:9 | LL | use alloc::slice::from_ref; | ^^^^^ help: consider importing the item from `core`: `core` diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs index 7d780c803ffd5..b07851e864f68 100644 --- a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs @@ -25,6 +25,17 @@ fn transmute_const() { } } +fn issue_11485() { + unsafe { + let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); + //~^ ERROR: transmuting a known null pointer into a function pointer + let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); + //~^ ERROR: transmuting a known null pointer into a function pointer + let _: fn() = std::mem::transmute(ZPTR as *const u8); + //~^ ERROR: transmuting a known null pointer into a function pointer + } +} + fn main() { one_liners(); transmute_const(); diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr index ab0ac0dd480bc..9073080cbf3c6 100644 --- a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr @@ -24,5 +24,29 @@ LL | let _: fn() = std::mem::transmute(ZPTR); | = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value -error: aborting due to 3 previous errors +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:30:23 + | +LL | let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:32:23 + | +LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:34:23 + | +LL | let _: fn() = std::mem::transmute(ZPTR as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs deleted file mode 100644 index f4e7f1943ae6d..0000000000000 --- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs +++ /dev/null @@ -1,534 +0,0 @@ -//@aux-build:proc_macro_unsafe.rs - -#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(clippy::let_unit_value, clippy::missing_safety_doc)] - -extern crate proc_macro_unsafe; - -// Valid comments - -fn nested_local() { - let _ = { - let _ = { - // SAFETY: - let _ = unsafe {}; - }; - }; -} - -fn deep_nest() { - let _ = { - let _ = { - // SAFETY: - let _ = unsafe {}; - - // Safety: - unsafe {}; - - let _ = { - let _ = { - let _ = { - let _ = { - let _ = { - // Safety: - let _ = unsafe {}; - - // SAFETY: - unsafe {}; - }; - }; - }; - - // Safety: - unsafe {}; - }; - }; - }; - - // Safety: - unsafe {}; - }; - - // SAFETY: - unsafe {}; -} - -fn local_tuple_expression() { - // Safety: - let _ = (42, unsafe {}); -} - -fn line_comment() { - // Safety: - unsafe {} -} - -fn line_comment_newlines() { - // SAFETY: - - unsafe {} -} - -fn line_comment_empty() { - // Safety: - // - // - // - unsafe {} -} - -fn line_comment_with_extras() { - // This is a description - // Safety: - unsafe {} -} - -fn block_comment() { - /* Safety: */ - unsafe {} -} - -fn block_comment_newlines() { - /* SAFETY: */ - - unsafe {} -} - -fn block_comment_with_extras() { - /* This is a description - * SAFETY: - */ - unsafe {} -} - -fn block_comment_terminator_same_line() { - /* This is a description - * Safety: */ - unsafe {} -} - -fn buried_safety() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor - // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation - // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - // laborum. Safety: - // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi - // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio - // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl - // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. - unsafe {} -} - -fn safety_with_prepended_text() { - // This is a test. safety: - unsafe {} -} - -fn local_line_comment() { - // Safety: - let _ = unsafe {}; -} - -fn local_block_comment() { - /* SAFETY: */ - let _ = unsafe {}; -} - -fn comment_array() { - // Safety: - let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; -} - -fn comment_tuple() { - // sAFETY: - let _ = (42, unsafe {}, "test", unsafe {}); -} - -fn comment_unary() { - // SAFETY: - let _ = *unsafe { &42 }; -} - -#[allow(clippy::match_single_binding)] -fn comment_match() { - // SAFETY: - let _ = match unsafe {} { - _ => {}, - }; -} - -fn comment_addr_of() { - // Safety: - let _ = &unsafe {}; -} - -fn comment_repeat() { - // Safety: - let _ = [unsafe {}; 5]; -} - -fn comment_macro_call() { - macro_rules! t { - ($b:expr) => { - $b - }; - } - - t!( - // SAFETY: - unsafe {} - ); -} - -fn comment_macro_def() { - macro_rules! t { - () => { - // Safety: - unsafe {} - }; - } - - t!(); -} - -fn non_ascii_comment() { - // ॐ᧻໒ SaFeTy: ௵∰ - unsafe {}; -} - -fn local_commented_block() { - let _ = - // safety: - unsafe {}; -} - -fn local_nest() { - // safety: - let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})]; -} - -fn in_fn_call(x: *const u32) { - fn f(x: u32) {} - - // Safety: reason - f(unsafe { *x }); -} - -fn multi_in_fn_call(x: *const u32) { - fn f(x: u32, y: u32) {} - - // Safety: reason - f(unsafe { *x }, unsafe { *x }); -} - -fn in_multiline_fn_call(x: *const u32) { - fn f(x: u32, y: u32) {} - - f( - // Safety: reason - unsafe { *x }, - 0, - ); -} - -fn in_macro_call(x: *const u32) { - // Safety: reason - println!("{}", unsafe { *x }); -} - -fn in_multiline_macro_call(x: *const u32) { - println!( - "{}", - // Safety: reason - unsafe { *x }, - ); -} - -fn from_proc_macro() { - proc_macro_unsafe::unsafe_block!(token); -} - -fn in_closure(x: *const u32) { - // Safety: reason - let _ = || unsafe { *x }; -} - -// Invalid comments - -#[rustfmt::skip] -fn inline_block_comment() { - /* Safety: */ unsafe {} -} - -fn no_comment() { - unsafe {} -} - -fn no_comment_array() { - let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; -} - -fn no_comment_tuple() { - let _ = (42, unsafe {}, "test", unsafe {}); -} - -fn no_comment_unary() { - let _ = *unsafe { &42 }; -} - -#[allow(clippy::match_single_binding)] -fn no_comment_match() { - let _ = match unsafe {} { - _ => {}, - }; -} - -fn no_comment_addr_of() { - let _ = &unsafe {}; -} - -fn no_comment_repeat() { - let _ = [unsafe {}; 5]; -} - -fn local_no_comment() { - let _ = unsafe {}; -} - -fn no_comment_macro_call() { - macro_rules! t { - ($b:expr) => { - $b - }; - } - - t!(unsafe {}); -} - -fn no_comment_macro_def() { - macro_rules! t { - () => { - unsafe {} - }; - } - - t!(); -} - -fn trailing_comment() { - unsafe {} // SAFETY: -} - -fn internal_comment() { - unsafe { - // SAFETY: - } -} - -fn interference() { - // SAFETY - - let _ = 42; - - unsafe {}; -} - -pub fn print_binary_tree() { - println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); -} - -mod unsafe_impl_smoke_test { - unsafe trait A {} - - // error: no safety comment - unsafe impl A for () {} - - // Safety: ok - unsafe impl A for (i32) {} - - mod sub_mod { - // error: - unsafe impl B for (u32) {} - unsafe trait B {} - } - - #[rustfmt::skip] - mod sub_mod2 { - // - // SAFETY: ok - // - - unsafe impl B for (u32) {} - unsafe trait B {} - } -} - -mod unsafe_impl_from_macro { - unsafe trait T {} - - // error - macro_rules! no_safety_comment { - ($t:ty) => { - unsafe impl T for $t {} - }; - } - - // ok - no_safety_comment!(()); - - // ok - macro_rules! with_safety_comment { - ($t:ty) => { - // SAFETY: - unsafe impl T for $t {} - }; - } - - // ok - with_safety_comment!((i32)); -} - -mod unsafe_impl_macro_and_not_macro { - unsafe trait T {} - - // error - macro_rules! no_safety_comment { - ($t:ty) => { - unsafe impl T for $t {} - }; - } - - // ok - no_safety_comment!(()); - - // error - unsafe impl T for (i32) {} - - // ok - no_safety_comment!(u32); - - // error - unsafe impl T for (bool) {} -} - -#[rustfmt::skip] -mod unsafe_impl_valid_comment { - unsafe trait SaFety {} - // SaFety: - unsafe impl SaFety for () {} - - unsafe trait MultiLineComment {} - // The following impl is safe - // ... - // Safety: reason - unsafe impl MultiLineComment for () {} - - unsafe trait NoAscii {} - // 安全 SAFETY: 以下のコードは安全です - unsafe impl NoAscii for () {} - - unsafe trait InlineAndPrecedingComment {} - // SAFETY: - /* comment */ unsafe impl InlineAndPrecedingComment for () {} - - unsafe trait BuriedSafety {} - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor - // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation - // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - // laborum. Safety: - // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi - // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio - // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl - // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. - unsafe impl BuriedSafety for () {} - - unsafe trait MultiLineBlockComment {} - /* This is a description - * Safety: */ - unsafe impl MultiLineBlockComment for () {} -} - -#[rustfmt::skip] -mod unsafe_impl_invalid_comment { - unsafe trait NoComment {} - - unsafe impl NoComment for () {} - - unsafe trait InlineComment {} - - /* SAFETY: */ unsafe impl InlineComment for () {} - - unsafe trait TrailingComment {} - - unsafe impl TrailingComment for () {} // SAFETY: - - unsafe trait Interference {} - // SAFETY: - const BIG_NUMBER: i32 = 1000000; - unsafe impl Interference for () {} -} - -unsafe trait ImplInFn {} - -fn impl_in_fn() { - // error - unsafe impl ImplInFn for () {} - - // SAFETY: ok - unsafe impl ImplInFn for (i32) {} -} - -unsafe trait CrateRoot {} - -// error -unsafe impl CrateRoot for () {} - -// SAFETY: ok -unsafe impl CrateRoot for (i32) {} - -fn issue_9142() { - // SAFETY: ok - let _ = - // we need this comment to avoid rustfmt putting - // it all on one line - unsafe {}; - - // SAFETY: this is more than one level away, so it should warn - let _ = { - if unsafe { true } { - todo!(); - } else { - let bar = unsafe {}; - todo!(); - bar - } - }; -} - -pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { - 1 -} - -pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { - 2 -} - -fn issue_10832() { - // Safety: A safety comment. But it will warn anyways - let _some_variable_with_a_very_long_name_to_break_the_line = - unsafe { a_function_with_a_very_long_name_to_break_the_line() }; - - // Safety: Another safety comment. But it will warn anyways - const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = - unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; - - // Safety: Yet another safety comment. But it will warn anyways - static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = - unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed index 87df1f8cb08fb..b17343aa9ba5a 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed @@ -23,7 +23,7 @@ fn unwrap_option_none() { let _val: u16 = 234; let _val: u16 = 234; let _val: u16 = { 234 }; - let _val: u16 = { 234 }; + let _val: u16 = { 234 }; panic!(); panic!("this always happens"); @@ -31,7 +31,7 @@ fn unwrap_option_none() { 234; 234; { 234 }; - { 234 }; + { 234 }; } fn unwrap_result_ok() { diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr index 013907f59c46f..4940091be60ae 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr @@ -116,7 +116,7 @@ LL | let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); help: remove the `None` and `unwrap_or_else()` | LL - let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); -LL + let _val: u16 = { 234 }; +LL + let _val: u16 = { 234 }; | error: used `unwrap()` on `None` value @@ -187,7 +187,7 @@ LL | None::.unwrap_or_else(|| -> u16 { 234 }); help: remove the `None` and `unwrap_or_else()` | LL - None::.unwrap_or_else(|| -> u16 { 234 }); -LL + { 234 }; +LL + { 234 }; | error: used `unwrap()` on `Ok` value diff --git a/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.fixed b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.fixed new file mode 100644 index 0000000000000..d0ba7ed749e4b --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.fixed @@ -0,0 +1,56 @@ +#![allow(unused)] +#![warn(clippy::unnecessary_map_on_constructor)] + +use std::ffi::OsStr; + +fn fun(t: i32) -> i32 { + t +} + +fn notfun(e: SimpleError) -> SimpleError { + e +} +macro_rules! expands_to_fun { + () => { + fun + }; +} + +#[derive(Copy, Clone)] +struct SimpleError {} + +type SimpleResult = std::result::Result; + +fn main() { + let x: i32 = 4; + + let err = SimpleError {}; + let a = Some(x); + let b: SimpleResult = Ok(x); + let c: SimpleResult = Err(err); + + let a = Some(fun(x)); + let b: SimpleResult = Ok(fun(x)); + let c: SimpleResult = Err(notfun(err)); + + let a = Option::Some(fun(x)); + let b: SimpleResult = SimpleResult::Ok(fun(x)); + let c: SimpleResult = SimpleResult::Err(notfun(err)); + let b: std::result::Result = Ok(fun(x)); + let c: std::result::Result = Err(notfun(err)); + + let a = Some(fun(x)); + let b: SimpleResult = Ok(fun(x)); + let c: SimpleResult = Err(notfun(err)); + + // Should not trigger warning + a.map(fun); + b.map(fun); + c.map_err(notfun); + + b.map_err(notfun); // Ok(_).map_err + c.map(fun); // Err(_).map() + + option_env!("PATH").map(OsStr::new); + Some(x).map(expands_to_fun!()); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.rs b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.rs new file mode 100644 index 0000000000000..e89e7aad4c40e --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.rs @@ -0,0 +1,56 @@ +#![allow(unused)] +#![warn(clippy::unnecessary_map_on_constructor)] + +use std::ffi::OsStr; + +fn fun(t: i32) -> i32 { + t +} + +fn notfun(e: SimpleError) -> SimpleError { + e +} +macro_rules! expands_to_fun { + () => { + fun + }; +} + +#[derive(Copy, Clone)] +struct SimpleError {} + +type SimpleResult = std::result::Result; + +fn main() { + let x: i32 = 4; + + let err = SimpleError {}; + let a = Some(x); + let b: SimpleResult = Ok(x); + let c: SimpleResult = Err(err); + + let a = Some(x).map(fun); + let b: SimpleResult = Ok(x).map(fun); + let c: SimpleResult = Err(err).map_err(notfun); + + let a = Option::Some(x).map(fun); + let b: SimpleResult = SimpleResult::Ok(x).map(fun); + let c: SimpleResult = SimpleResult::Err(err).map_err(notfun); + let b: std::result::Result = Ok(x).map(fun); + let c: std::result::Result = Err(err).map_err(notfun); + + let a = Some(fun(x)); + let b: SimpleResult = Ok(fun(x)); + let c: SimpleResult = Err(notfun(err)); + + // Should not trigger warning + a.map(fun); + b.map(fun); + c.map_err(notfun); + + b.map_err(notfun); // Ok(_).map_err + c.map(fun); // Err(_).map() + + option_env!("PATH").map(OsStr::new); + Some(x).map(expands_to_fun!()); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.stderr b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.stderr new file mode 100644 index 0000000000000..d522b68d8726a --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_on_constructor.stderr @@ -0,0 +1,53 @@ +error: unnecessary map on constructor Some(_) + --> $DIR/unnecessary_map_on_constructor.rs:32:13 + | +LL | let a = Some(x).map(fun); + | ^^^^^^^^^^^^^^^^ help: try: `Some(fun(x))` + | + = note: `-D clippy::unnecessary-map-on-constructor` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_on_constructor)]` + +error: unnecessary map on constructor Ok(_) + --> $DIR/unnecessary_map_on_constructor.rs:33:27 + | +LL | let b: SimpleResult = Ok(x).map(fun); + | ^^^^^^^^^^^^^^ help: try: `Ok(fun(x))` + +error: unnecessary map_err on constructor Err(_) + --> $DIR/unnecessary_map_on_constructor.rs:34:27 + | +LL | let c: SimpleResult = Err(err).map_err(notfun); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Err(notfun(err))` + +error: unnecessary map on constructor Option::Some(_) + --> $DIR/unnecessary_map_on_constructor.rs:36:13 + | +LL | let a = Option::Some(x).map(fun); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Option::Some(fun(x))` + +error: unnecessary map on constructor SimpleResult::Ok(_) + --> $DIR/unnecessary_map_on_constructor.rs:37:27 + | +LL | let b: SimpleResult = SimpleResult::Ok(x).map(fun); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `SimpleResult::Ok(fun(x))` + +error: unnecessary map_err on constructor SimpleResult::Err(_) + --> $DIR/unnecessary_map_on_constructor.rs:38:27 + | +LL | let c: SimpleResult = SimpleResult::Err(err).map_err(notfun); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `SimpleResult::Err(notfun(err))` + +error: unnecessary map on constructor Ok(_) + --> $DIR/unnecessary_map_on_constructor.rs:39:52 + | +LL | let b: std::result::Result = Ok(x).map(fun); + | ^^^^^^^^^^^^^^ help: try: `Ok(fun(x))` + +error: unnecessary map_err on constructor Err(_) + --> $DIR/unnecessary_map_on_constructor.rs:40:52 + | +LL | let c: std::result::Result = Err(err).map_err(notfun); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Err(notfun(err))` + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed index 7b662ca92d2ae..67faabc53cb5e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed @@ -1,4 +1,4 @@ -#![allow(clippy::needless_borrow, clippy::ptr_arg)] +#![allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs index d79778a6a2ed4..99f9136427d4d 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_borrow, clippy::ptr_arg)] +#![allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index c672eff1c2710..a8f404b1400c9 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -1,6 +1,5 @@ //@aux-build:proc_macro_derive.rs -#![feature(rustc_private)] -#![warn(clippy::all)] +#![feature(rustc_private, lint_reasons)] #![warn(clippy::used_underscore_binding)] #![allow(clippy::disallowed_names, clippy::eq_op, clippy::uninlined_format_args)] @@ -107,6 +106,31 @@ async fn await_desugaring() { .await } +struct PhantomField { + _marker: std::marker::PhantomData, +} + +impl std::fmt::Debug for PhantomField { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("PhantomField").field("_marker", &self._marker).finish() + } +} + +struct AllowedField { + #[allow(clippy::used_underscore_binding)] + _allowed: usize, +} + +struct ExpectedField { + #[expect(clippy::used_underscore_binding)] + _expected: usize, +} + +fn lint_levels(allowed: AllowedField, expected: ExpectedField) { + let _ = allowed._allowed; + let _ = expected._expected; +} + fn main() { let foo = 0u32; // tests of unused_underscore lint diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr index 289519b172eeb..78d8279810c1f 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr @@ -1,41 +1,76 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:24:5 + --> $DIR/used_underscore_binding.rs:23:5 | LL | _foo + 1 | ^^^^ | +note: `_foo` is defined here + --> $DIR/used_underscore_binding.rs:22:22 + | +LL | fn prefix_underscore(_foo: u32) -> u32 { + | ^^^^ = note: `-D clippy::used-underscore-binding` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::used_underscore_binding)]` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:29:20 + --> $DIR/used_underscore_binding.rs:28:20 | LL | println!("{}", _foo); | ^^^^ + | +note: `_foo` is defined here + --> $DIR/used_underscore_binding.rs:27:24 + | +LL | fn in_macro_or_desugar(_foo: u32) { + | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:30:16 + --> $DIR/used_underscore_binding.rs:29:16 | LL | assert_eq!(_foo, _foo); | ^^^^ + | +note: `_foo` is defined here + --> $DIR/used_underscore_binding.rs:27:24 + | +LL | fn in_macro_or_desugar(_foo: u32) { + | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:30:22 + --> $DIR/used_underscore_binding.rs:29:22 | LL | assert_eq!(_foo, _foo); | ^^^^ + | +note: `_foo` is defined here + --> $DIR/used_underscore_binding.rs:27:24 + | +LL | fn in_macro_or_desugar(_foo: u32) { + | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:43:5 + --> $DIR/used_underscore_binding.rs:42:5 | LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ + | +note: `_underscore_field` is defined here + --> $DIR/used_underscore_binding.rs:36:5 + | +LL | _underscore_field: u32, + | ^^^^^^^^^^^^^^^^^^^^^^ error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:104:16 + --> $DIR/used_underscore_binding.rs:103:16 | LL | uses_i(_i); | ^^ + | +note: `_i` is defined here + --> $DIR/used_underscore_binding.rs:102:13 + | +LL | let _i = 5; + | ^^ error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed index 5259195990592..ed8387b7eb2c5 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.fixed +++ b/src/tools/clippy/tests/ui/useless_conversion.fixed @@ -151,6 +151,8 @@ fn main() { let _ = s3; let s4: Foo<'a'> = Foo; let _ = vec![s4, s4, s4].into_iter(); + + issue11300::bar(); } #[allow(dead_code)] @@ -196,6 +198,95 @@ fn explicit_into_iter_fn_arg() { b(macro_generated!()); } +mod issue11300 { + pub fn foo(i: I) + where + I: IntoIterator + ExactSizeIterator, + { + assert_eq!(i.len(), 3); + } + + trait Helper {} + impl Helper for [i32; 3] {} + impl Helper for std::array::IntoIter {} + impl Helper<()> for std::array::IntoIter {} + + fn foo2(_: I) + where + I: IntoIterator + Helper, + { + } + + trait Helper2 {} + impl Helper2> for i32 {} + impl Helper2<[i32; 3]> for i32 {} + fn foo3(_: I) + where + I: IntoIterator, + i32: Helper2, + { + } + + pub fn bar() { + // This should not trigger the lint: + // `[i32, 3]` does not satisfy the `ExactSizeIterator` bound, so the into_iter call cannot be + // removed and is not useless. + foo([1, 2, 3].into_iter()); + + // This should trigger the lint, receiver type [i32; 3] also implements `Helper` + foo2::([1, 2, 3]); + + // This again should *not* lint, since X = () and I = std::array::IntoIter, + // and `[i32; 3]: Helper<()>` is not true (only `std::array::IntoIter: Helper<()>` is). + foo2::<(), _>([1, 2, 3].into_iter()); + + // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`, + // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary. + foo3([1, 2, 3]); + } + + fn ice() { + struct S1; + impl S1 { + pub fn foo(&self, _: I) {} + } + + S1.foo([1, 2]); + + // ICE that occured in itertools + trait Itertools { + fn interleave_shortest(self, other: J) + where + J: IntoIterator, + Self: Sized; + } + impl Itertools for I { + fn interleave_shortest(self, other: J) + where + J: IntoIterator, + Self: Sized, + { + } + } + let v0: Vec = vec![0, 2, 4]; + let v1: Vec = vec![1, 3, 5, 7]; + v0.into_iter().interleave_shortest(v1); + + trait TraitWithLifetime<'a> {} + impl<'a> TraitWithLifetime<'a> for std::array::IntoIter<&'a i32, 2> {} + + struct Helper; + impl<'a> Helper { + fn with_lt(&self, _: I) + where + I: IntoIterator + TraitWithLifetime<'a>, + { + } + } + Helper.with_lt([&1, &2].into_iter()); + } +} + #[derive(Copy, Clone)] struct Foo; diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs index befb2f9a5c32c..991a7762fc64a 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.rs +++ b/src/tools/clippy/tests/ui/useless_conversion.rs @@ -151,6 +151,8 @@ fn main() { let _ = Foo::<'a'>::from(s3); let s4: Foo<'a'> = Foo; let _ = vec![s4, s4, s4].into_iter().into_iter(); + + issue11300::bar(); } #[allow(dead_code)] @@ -196,6 +198,95 @@ fn explicit_into_iter_fn_arg() { b(macro_generated!()); } +mod issue11300 { + pub fn foo(i: I) + where + I: IntoIterator + ExactSizeIterator, + { + assert_eq!(i.len(), 3); + } + + trait Helper {} + impl Helper for [i32; 3] {} + impl Helper for std::array::IntoIter {} + impl Helper<()> for std::array::IntoIter {} + + fn foo2(_: I) + where + I: IntoIterator + Helper, + { + } + + trait Helper2 {} + impl Helper2> for i32 {} + impl Helper2<[i32; 3]> for i32 {} + fn foo3(_: I) + where + I: IntoIterator, + i32: Helper2, + { + } + + pub fn bar() { + // This should not trigger the lint: + // `[i32, 3]` does not satisfy the `ExactSizeIterator` bound, so the into_iter call cannot be + // removed and is not useless. + foo([1, 2, 3].into_iter()); + + // This should trigger the lint, receiver type [i32; 3] also implements `Helper` + foo2::([1, 2, 3].into_iter()); + + // This again should *not* lint, since X = () and I = std::array::IntoIter, + // and `[i32; 3]: Helper<()>` is not true (only `std::array::IntoIter: Helper<()>` is). + foo2::<(), _>([1, 2, 3].into_iter()); + + // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`, + // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary. + foo3([1, 2, 3].into_iter()); + } + + fn ice() { + struct S1; + impl S1 { + pub fn foo(&self, _: I) {} + } + + S1.foo([1, 2].into_iter()); + + // ICE that occured in itertools + trait Itertools { + fn interleave_shortest(self, other: J) + where + J: IntoIterator, + Self: Sized; + } + impl Itertools for I { + fn interleave_shortest(self, other: J) + where + J: IntoIterator, + Self: Sized, + { + } + } + let v0: Vec = vec![0, 2, 4]; + let v1: Vec = vec![1, 3, 5, 7]; + v0.into_iter().interleave_shortest(v1.into_iter()); + + trait TraitWithLifetime<'a> {} + impl<'a> TraitWithLifetime<'a> for std::array::IntoIter<&'a i32, 2> {} + + struct Helper; + impl<'a> Helper { + fn with_lt(&self, _: I) + where + I: IntoIterator + TraitWithLifetime<'a>, + { + } + } + Helper.with_lt([&1, &2].into_iter()); + } +} + #[derive(Copy, Clone)] struct Foo; diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index 28e7bb61098f7..c1f8b6b4aa966 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -119,64 +119,112 @@ LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/useless_conversion.rs:183:7 + --> $DIR/useless_conversion.rs:185:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/useless_conversion.rs:173:13 + --> $DIR/useless_conversion.rs:175:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/useless_conversion.rs:184:7 + --> $DIR/useless_conversion.rs:186:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/useless_conversion.rs:174:18 + --> $DIR/useless_conversion.rs:176:18 | LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/useless_conversion.rs:185:7 + --> $DIR/useless_conversion.rs:187:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/useless_conversion.rs:177:12 + --> $DIR/useless_conversion.rs:179:12 | LL | T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/useless_conversion.rs:188:7 + --> $DIR/useless_conversion.rs:190:7 | LL | b(vec![1, 2].into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/useless_conversion.rs:173:13 + --> $DIR/useless_conversion.rs:175:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/useless_conversion.rs:189:7 + --> $DIR/useless_conversion.rs:191:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/useless_conversion.rs:173:13 + --> $DIR/useless_conversion.rs:175:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 24 previous errors +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:237:24 + | +LL | foo2::([1, 2, 3].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:216:12 + | +LL | I: IntoIterator + Helper, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:245:14 + | +LL | foo3([1, 2, 3].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:225:12 + | +LL | I: IntoIterator, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:254:16 + | +LL | S1.foo([1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:251:27 + | +LL | pub fn foo(&self, _: I) {} + | ^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:273:44 + | +LL | v0.into_iter().interleave_shortest(v1.into_iter()); + | ^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `v1` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:260:20 + | +LL | J: IntoIterator, + | ^^^^^^^^^^^^ + +error: aborting due to 28 previous errors diff --git a/src/tools/clippy/tests/ui/vec_box_sized.fixed b/src/tools/clippy/tests/ui/vec_box_sized.fixed index 4a5ef83856a41..4363d2224afd2 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.fixed +++ b/src/tools/clippy/tests/ui/vec_box_sized.fixed @@ -49,4 +49,9 @@ mod inner_mod { } } +// https://github.com/rust-lang/rust-clippy/issues/11417 +fn in_closure() { + let _ = |_: Vec>| {}; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/vec_box_sized.rs b/src/tools/clippy/tests/ui/vec_box_sized.rs index ea020405a30f0..f4e27fe4bd509 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.rs +++ b/src/tools/clippy/tests/ui/vec_box_sized.rs @@ -49,4 +49,9 @@ mod inner_mod { } } +// https://github.com/rust-lang/rust-clippy/issues/11417 +fn in_closure() { + let _ = |_: Vec>| {}; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index 2828f9d048efc..6fdd728b9b72e 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -69,6 +69,34 @@ mod struct_mod { } } +// issue 9942 +mod underscore_mod { + // allow use of `deref` so that `clippy --fix` includes `Deref`. + #![allow(noop_method_call)] + + mod exports_underscore { + pub use std::ops::Deref as _; + pub fn dummy() {} + } + + mod exports_underscore_ish { + pub use std::ops::Deref as _Deref; + pub fn dummy() {} + } + + fn does_not_lint() { + use self::exports_underscore::*; + let _ = (&0).deref(); + dummy(); + } + + fn does_lint() { + use self::exports_underscore_ish::{_Deref, dummy}; + let _ = (&0).deref(); + dummy(); + } +} + fn main() { foo(); multi_foo(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs index cbe70e505d8cd..20e06d4b36641 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports.rs @@ -69,6 +69,34 @@ mod struct_mod { } } +// issue 9942 +mod underscore_mod { + // allow use of `deref` so that `clippy --fix` includes `Deref`. + #![allow(noop_method_call)] + + mod exports_underscore { + pub use std::ops::Deref as _; + pub fn dummy() {} + } + + mod exports_underscore_ish { + pub use std::ops::Deref as _Deref; + pub fn dummy() {} + } + + fn does_not_lint() { + use self::exports_underscore::*; + let _ = (&0).deref(); + dummy(); + } + + fn does_lint() { + use self::exports_underscore_ish::*; + let _ = (&0).deref(); + dummy(); + } +} + fn main() { foo(); multi_foo(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index 3c750815bafc9..01a5414778c10 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:97:13 + --> $DIR/wildcard_imports.rs:94:13 + | +LL | use self::exports_underscore_ish::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `self::exports_underscore_ish::{_Deref, dummy}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:125:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:103:75 + --> $DIR/wildcard_imports.rs:131:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:104:13 + --> $DIR/wildcard_imports.rs:132:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:116:20 + --> $DIR/wildcard_imports.rs:144:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:116:30 + --> $DIR/wildcard_imports.rs:144:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:123:13 + --> $DIR/wildcard_imports.rs:151:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:152:9 + --> $DIR/wildcard_imports.rs:180:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:161:9 + --> $DIR/wildcard_imports.rs:189:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:162:9 + --> $DIR/wildcard_imports.rs:190:9 | LL | use crate:: fn_mod:: | _________^ @@ -94,40 +100,40 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:173:13 + --> $DIR/wildcard_imports.rs:201:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:208:17 + --> $DIR/wildcard_imports.rs:236:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:216:13 + --> $DIR/wildcard_imports.rs:244:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:225:17 + --> $DIR/wildcard_imports.rs:253:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:234:13 + --> $DIR/wildcard_imports.rs:262:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:242:13 + --> $DIR/wildcard_imports.rs:270:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` -error: aborting due to 21 previous errors +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed index b27281fa25c56..6a9fe007d654d 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -64,6 +64,34 @@ mod struct_mod { } } +// issue 9942 +mod underscore_mod { + // allow use of `deref` so that `clippy --fix` includes `Deref`. + #![allow(noop_method_call)] + + mod exports_underscore { + pub use std::ops::Deref as _; + pub fn dummy() {} + } + + mod exports_underscore_ish { + pub use std::ops::Deref as _Deref; + pub fn dummy() {} + } + + fn does_not_lint() { + use exports_underscore::*; + let _ = (&0).deref(); + dummy(); + } + + fn does_lint() { + use exports_underscore_ish::{_Deref, dummy}; + let _ = (&0).deref(); + dummy(); + } +} + fn main() { foo(); multi_foo(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr index 709a665d65c2a..e39f240a4aa2a 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:91:13 + --> $DIR/wildcard_imports_2021.rs:89:13 + | +LL | use exports_underscore_ish::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:119:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:97:75 + --> $DIR/wildcard_imports_2021.rs:125:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:98:13 + --> $DIR/wildcard_imports_2021.rs:126:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:110:20 + --> $DIR/wildcard_imports_2021.rs:138:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:110:30 + --> $DIR/wildcard_imports_2021.rs:138:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:117:13 + --> $DIR/wildcard_imports_2021.rs:145:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:146:9 + --> $DIR/wildcard_imports_2021.rs:174:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:155:9 + --> $DIR/wildcard_imports_2021.rs:183:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:156:9 + --> $DIR/wildcard_imports_2021.rs:184:9 | LL | use crate:: fn_mod:: | _________^ @@ -94,40 +100,40 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:167:13 + --> $DIR/wildcard_imports_2021.rs:195:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:202:17 + --> $DIR/wildcard_imports_2021.rs:230:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:210:13 + --> $DIR/wildcard_imports_2021.rs:238:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:219:17 + --> $DIR/wildcard_imports_2021.rs:247:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:228:13 + --> $DIR/wildcard_imports_2021.rs:256:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:236:13 + --> $DIR/wildcard_imports_2021.rs:264:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` -error: aborting due to 21 previous errors +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed index b27281fa25c56..6a9fe007d654d 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -64,6 +64,34 @@ mod struct_mod { } } +// issue 9942 +mod underscore_mod { + // allow use of `deref` so that `clippy --fix` includes `Deref`. + #![allow(noop_method_call)] + + mod exports_underscore { + pub use std::ops::Deref as _; + pub fn dummy() {} + } + + mod exports_underscore_ish { + pub use std::ops::Deref as _Deref; + pub fn dummy() {} + } + + fn does_not_lint() { + use exports_underscore::*; + let _ = (&0).deref(); + dummy(); + } + + fn does_lint() { + use exports_underscore_ish::{_Deref, dummy}; + let _ = (&0).deref(); + dummy(); + } +} + fn main() { foo(); multi_foo(); diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr index 709a665d65c2a..e39f240a4aa2a 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:91:13 + --> $DIR/wildcard_imports_2021.rs:89:13 + | +LL | use exports_underscore_ish::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:119:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:97:75 + --> $DIR/wildcard_imports_2021.rs:125:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:98:13 + --> $DIR/wildcard_imports_2021.rs:126:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:110:20 + --> $DIR/wildcard_imports_2021.rs:138:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:110:30 + --> $DIR/wildcard_imports_2021.rs:138:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:117:13 + --> $DIR/wildcard_imports_2021.rs:145:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:146:9 + --> $DIR/wildcard_imports_2021.rs:174:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:155:9 + --> $DIR/wildcard_imports_2021.rs:183:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:156:9 + --> $DIR/wildcard_imports_2021.rs:184:9 | LL | use crate:: fn_mod:: | _________^ @@ -94,40 +100,40 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:167:13 + --> $DIR/wildcard_imports_2021.rs:195:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:202:17 + --> $DIR/wildcard_imports_2021.rs:230:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:210:13 + --> $DIR/wildcard_imports_2021.rs:238:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:219:17 + --> $DIR/wildcard_imports_2021.rs:247:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:228:13 + --> $DIR/wildcard_imports_2021.rs:256:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:236:13 + --> $DIR/wildcard_imports_2021.rs:264:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` -error: aborting due to 21 previous errors +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs index 7dd2103eca7e7..18ebc0f512741 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs @@ -64,6 +64,34 @@ mod struct_mod { } } +// issue 9942 +mod underscore_mod { + // allow use of `deref` so that `clippy --fix` includes `Deref`. + #![allow(noop_method_call)] + + mod exports_underscore { + pub use std::ops::Deref as _; + pub fn dummy() {} + } + + mod exports_underscore_ish { + pub use std::ops::Deref as _Deref; + pub fn dummy() {} + } + + fn does_not_lint() { + use exports_underscore::*; + let _ = (&0).deref(); + dummy(); + } + + fn does_lint() { + use exports_underscore_ish::*; + let _ = (&0).deref(); + dummy(); + } +} + fn main() { foo(); multi_foo(); diff --git a/src/tools/clippy/tests/ui/write_literal.fixed b/src/tools/clippy/tests/ui/write_literal.fixed index ee577574d2898..3d216b76cbf3d 100644 --- a/src/tools/clippy/tests/ui/write_literal.fixed +++ b/src/tools/clippy/tests/ui/write_literal.fixed @@ -43,16 +43,22 @@ fn main() { // throw a warning writeln!(v, "hello world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string writeln!(v, "world hello"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // named args shouldn't change anything either writeln!(v, "hello world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string writeln!(v, "world hello"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string + + // #10128 + writeln!(v, "hello {0} world", 2); + //~^ ERROR: literal with an empty format string + writeln!(v, "world {0} hello", 2); + //~^ ERROR: literal with an empty format string + writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4); + //~^ ERROR: literal with an empty format string + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4); + //~^ ERROR: literal with an empty format string } diff --git a/src/tools/clippy/tests/ui/write_literal.rs b/src/tools/clippy/tests/ui/write_literal.rs index 588e8fd413a48..79d6daa2e3b5e 100644 --- a/src/tools/clippy/tests/ui/write_literal.rs +++ b/src/tools/clippy/tests/ui/write_literal.rs @@ -43,16 +43,22 @@ fn main() { // throw a warning writeln!(v, "{0} {1}", "hello", "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string writeln!(v, "{1} {0}", "hello", "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // named args shouldn't change anything either writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string + + // #10128 + writeln!(v, "{0} {1} {2}", "hello", 2, "world"); + //~^ ERROR: literal with an empty format string + writeln!(v, "{2} {1} {0}", "hello", 2, "world"); + //~^ ERROR: literal with an empty format string + writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4); + //~^ ERROR: literal with an empty format string + writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4); + //~^ ERROR: literal with an empty format string } diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr index 372a54cf769fb..ee0d536e954f3 100644 --- a/src/tools/clippy/tests/ui/write_literal.stderr +++ b/src/tools/clippy/tests/ui/write_literal.stderr @@ -52,96 +52,96 @@ error: literal with an empty format string --> $DIR/write_literal.rs:44:28 | LL | writeln!(v, "{0} {1}", "hello", "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^^^^ | help: try | LL - writeln!(v, "{0} {1}", "hello", "world"); -LL + writeln!(v, "hello {1}", "world"); +LL + writeln!(v, "hello world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:44:37 + --> $DIR/write_literal.rs:46:28 | -LL | writeln!(v, "{0} {1}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{1} {0}", "hello", "world"); + | ^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{0} {1}", "hello", "world"); -LL + writeln!(v, "{0} world", "hello"); +LL - writeln!(v, "{1} {0}", "hello", "world"); +LL + writeln!(v, "world hello"); | error: literal with an empty format string - --> $DIR/write_literal.rs:47:37 + --> $DIR/write_literal.rs:50:38 | -LL | writeln!(v, "{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{1} {0}", "hello", "world"); -LL + writeln!(v, "world {0}", "hello"); +LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); +LL + writeln!(v, "hello world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:47:28 + --> $DIR/write_literal.rs:52:38 | -LL | writeln!(v, "{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{1} {0}", "hello", "world"); -LL + writeln!(v, "{1} hello", "world"); +LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); +LL + writeln!(v, "world hello"); | error: literal with an empty format string - --> $DIR/write_literal.rs:52:38 + --> $DIR/write_literal.rs:56:32 | -LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | writeln!(v, "{0} {1} {2}", "hello", 2, "world"); + | ^^^^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); -LL + writeln!(v, "hello {bar}", bar = "world"); +LL - writeln!(v, "{0} {1} {2}", "hello", 2, "world"); +LL + writeln!(v, "hello {0} world", 2); | error: literal with an empty format string - --> $DIR/write_literal.rs:52:53 + --> $DIR/write_literal.rs:58:32 | -LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | writeln!(v, "{2} {1} {0}", "hello", 2, "world"); + | ^^^^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); -LL + writeln!(v, "{foo} world", foo = "hello"); +LL - writeln!(v, "{2} {1} {0}", "hello", 2, "world"); +LL + writeln!(v, "world {0} hello", 2); | error: literal with an empty format string - --> $DIR/write_literal.rs:55:53 + --> $DIR/write_literal.rs:60:39 | -LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4); + | ^^^^^^^ | help: try | -LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); -LL + writeln!(v, "world {foo}", foo = "hello"); +LL - writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4); +LL + writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4); | error: literal with an empty format string - --> $DIR/write_literal.rs:55:38 + --> $DIR/write_literal.rs:62:41 | -LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ +LL | writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4); + | ^^^^^^^^^^^^^^^^^^^^^^ | help: try | -LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); -LL + writeln!(v, "{bar} hello", bar = "world"); +LL - writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4); +LL + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4); | error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs index aa0c13c134080..b2ed552d46bcc 100644 --- a/src/tools/clippy/tests/ui/write_literal_2.rs +++ b/src/tools/clippy/tests/ui/write_literal_2.rs @@ -1,6 +1,6 @@ //@no-rustfix: overlapping suggestions #![allow(unused_must_use)] -#![warn(clippy::needless_raw_strings, clippy::write_literal)] +#![warn(clippy::write_literal)] use std::io::Write; @@ -11,9 +11,7 @@ fn main() { //~^ ERROR: literal with an empty format string //~| NOTE: `-D clippy::write-literal` implied by `-D warnings` writeln!(v, r"{}", r"{hello}"); - //~^ ERROR: unnecessary raw string literal - //~| NOTE: `-D clippy::needless-raw-strings` implied by `-D warnings` - //~| ERROR: literal with an empty format string + //~^ ERROR: literal with an empty format string writeln!(v, "{}", '\''); //~^ ERROR: literal with an empty format string writeln!(v, "{}", '"'); @@ -26,17 +24,14 @@ fn main() { v, "some {}", "hello \ - //~^ ERROR: literal with an empty format string - world!" + world!", + //~^^ ERROR: literal with an empty format string ); writeln!( v, "some {}\ {} \\ {}", - "1", - "2", - "3", - //~^ ERROR: literal with an empty format string + "1", "2", "3", ); writeln!(v, "{}", "\\"); //~^ ERROR: literal with an empty format string @@ -51,7 +46,6 @@ fn main() { // hard mode writeln!(v, r#"{}{}"#, '#', '"'); //~^ ERROR: literal with an empty format string - //~| ERROR: literal with an empty format string // should not lint writeln!(v, r"{}", "\r"); } diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr index 6d382a267ad81..81ef49de082e7 100644 --- a/src/tools/clippy/tests/ui/write_literal_2.stderr +++ b/src/tools/clippy/tests/ui/write_literal_2.stderr @@ -1,14 +1,3 @@ -error: unnecessary raw string literal - --> $DIR/write_literal_2.rs:13:24 - | -LL | writeln!(v, r"{}", r"{hello}"); - | -^^^^^^^^^ - | | - | help: use a string literal instead: `"{hello}"` - | - = note: `-D clippy::needless-raw-strings` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]` - error: literal with an empty format string --> $DIR/write_literal_2.rs:10:23 | @@ -36,7 +25,7 @@ LL + writeln!(v, r"{{hello}}"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:17:23 + --> $DIR/write_literal_2.rs:15:23 | LL | writeln!(v, "{}", '\''); | ^^^^ @@ -48,7 +37,7 @@ LL + writeln!(v, "'"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:19:23 + --> $DIR/write_literal_2.rs:17:23 | LL | writeln!(v, "{}", '"'); | ^^^ @@ -60,13 +49,13 @@ LL + writeln!(v, "\""); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:21:24 + --> $DIR/write_literal_2.rs:19:24 | LL | writeln!(v, r"{}", '"'); | ^^^ error: literal with an empty format string - --> $DIR/write_literal_2.rs:23:24 + --> $DIR/write_literal_2.rs:21:24 | LL | writeln!(v, r"{}", '\''); | ^^^^ @@ -78,59 +67,32 @@ LL + writeln!(v, r"'"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:28:9 + --> $DIR/write_literal_2.rs:26:9 | LL | / "hello \ -LL | | -LL | | world!" +LL | | world!", | |_______________^ | help: try | LL ~ "some hello \ -LL + -LL ~ world!" +LL ~ world!", | error: literal with an empty format string - --> $DIR/write_literal_2.rs:36:9 + --> $DIR/write_literal_2.rs:34:9 | -LL | "1", - | ^^^ +LL | "1", "2", "3", + | ^^^^^^^^^^^^^ | help: try | LL ~ "some 1\ -LL ~ {} \\ {}", +LL ~ 2 \\ 3", | error: literal with an empty format string - --> $DIR/write_literal_2.rs:37:9 - | -LL | "2", - | ^^^ - | -help: try - | -LL ~ 2 \\ {}", -LL ~ "1", - | - -error: literal with an empty format string - --> $DIR/write_literal_2.rs:38:9 - | -LL | "3", - | ^^^ - | -help: try - | -LL ~ {} \\ 3", -LL | "1", -LL ~ "2", - | - -error: literal with an empty format string - --> $DIR/write_literal_2.rs:41:23 + --> $DIR/write_literal_2.rs:36:23 | LL | writeln!(v, "{}", "\\"); | ^^^^ @@ -142,7 +104,7 @@ LL + writeln!(v, "\\"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:43:24 + --> $DIR/write_literal_2.rs:38:24 | LL | writeln!(v, r"{}", "\\"); | ^^^^ @@ -154,7 +116,7 @@ LL + writeln!(v, r"\"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:45:26 + --> $DIR/write_literal_2.rs:40:26 | LL | writeln!(v, r#"{}"#, "\\"); | ^^^^ @@ -166,7 +128,7 @@ LL + writeln!(v, r#"\"#); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:47:23 + --> $DIR/write_literal_2.rs:42:23 | LL | writeln!(v, "{}", r"\"); | ^^^^ @@ -178,7 +140,7 @@ LL + writeln!(v, "\\"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:49:23 + --> $DIR/write_literal_2.rs:44:23 | LL | writeln!(v, "{}", "\r"); | ^^^^ @@ -190,16 +152,10 @@ LL + writeln!(v, "\r"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:52:28 - | -LL | writeln!(v, r#"{}{}"#, '#', '"'); - | ^^^ - -error: literal with an empty format string - --> $DIR/write_literal_2.rs:52:33 + --> $DIR/write_literal_2.rs:47:28 | LL | writeln!(v, r#"{}{}"#, '#', '"'); - | ^^^ + | ^^^^^^^^ -error: aborting due to 18 previous errors +error: aborting due to 14 previous errors diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b91d5a958bb62..0e1bf0c6c2dce 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -141,6 +141,22 @@ impl PanicStrategy { } } +#[derive(Clone, Debug, PartialEq, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum Sanitizer { + Address, + Cfi, + Kcfi, + KernelAddress, + Leak, + Memory, + Memtag, + Safestack, + ShadowCallStack, + Thread, + Hwaddress, +} + /// Configuration for compiletest #[derive(Debug, Default, Clone)] pub struct Config { @@ -560,6 +576,12 @@ pub struct TargetCfg { pub(crate) panic: PanicStrategy, #[serde(default)] pub(crate) dynamic_linking: bool, + #[serde(rename = "supported-sanitizers", default)] + pub(crate) sanitizers: Vec, + #[serde(rename = "supports-xray", default)] + pub(crate) xray: bool, + #[serde(default = "default_reloc_model")] + pub(crate) relocation_model: String, } impl TargetCfg { @@ -572,6 +594,10 @@ fn default_os() -> String { "none".into() } +fn default_reloc_model() -> String { + "pic".into() +} + #[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)] #[serde(rename_all = "kebab-case")] pub enum Endian { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 62364ede47b38..4a40fb55f5c16 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,6 +1,5 @@ -use crate::common::{Config, Debugger}; +use crate::common::{Config, Debugger, Sanitizer}; use crate::header::IgnoreDecision; -use crate::util; pub(super) fn handle_needs( cache: &CachedNeedsConditions, @@ -135,6 +134,11 @@ pub(super) fn handle_needs( condition: config.target_cfg().dynamic_linking, ignore_reason: "ignored on targets without dynamic linking", }, + Need { + name: "needs-relocation-model-pic", + condition: config.target_cfg().relocation_model == "pic", + ignore_reason: "ignored on targets without PIC relocation model", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { @@ -220,24 +224,25 @@ impl CachedNeedsConditions { path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file()); let target = &&*config.target; + let sanitizers = &config.target_cfg().sanitizers; Self { sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(), - sanitizer_address: util::ASAN_SUPPORTED_TARGETS.contains(target), - sanitizer_cfi: util::CFI_SUPPORTED_TARGETS.contains(target), - sanitizer_kcfi: util::KCFI_SUPPORTED_TARGETS.contains(target), - sanitizer_kasan: util::KASAN_SUPPORTED_TARGETS.contains(target), - sanitizer_leak: util::LSAN_SUPPORTED_TARGETS.contains(target), - sanitizer_memory: util::MSAN_SUPPORTED_TARGETS.contains(target), - sanitizer_thread: util::TSAN_SUPPORTED_TARGETS.contains(target), - sanitizer_hwaddress: util::HWASAN_SUPPORTED_TARGETS.contains(target), - sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target), - sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target), - sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target), + sanitizer_address: sanitizers.contains(&Sanitizer::Address), + sanitizer_cfi: sanitizers.contains(&Sanitizer::Cfi), + sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi), + sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress), + sanitizer_leak: sanitizers.contains(&Sanitizer::Leak), + sanitizer_memory: sanitizers.contains(&Sanitizer::Memory), + sanitizer_thread: sanitizers.contains(&Sanitizer::Thread), + sanitizer_hwaddress: sanitizers.contains(&Sanitizer::Hwaddress), + sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), + sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), + sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(), - xray: util::XRAY_SUPPORTED_TARGETS.contains(target), + xray: config.target_cfg().xray, - // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find - // whether `rust-lld` is present in the compiler under test. + // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), + // we need to find whether `rust-lld` is present in the compiler under test. // // The --compile-lib-path is the path to host shared libraries, but depends on the OS. For // example: diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 362fba11697be..2fd80b52ceeee 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -53,47 +53,117 @@ fn test_parse_normalization_string() { assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#); } -fn config() -> Config { - let args = &[ - "compiletest", - "--mode=ui", - "--suite=ui", - "--compile-lib-path=", - "--run-lib-path=", - "--python=", - "--jsondocck-path=", - "--src-base=", - "--build-base=", - "--sysroot-base=", - "--stage-id=stage2-x86_64-unknown-linux-gnu", - "--cc=c", - "--cxx=c++", - "--cflags=", - "--cxxflags=", - "--llvm-components=", - "--android-cross-path=", - "--target=x86_64-unknown-linux-gnu", - "--channel=nightly", - ]; - let mut args: Vec = args.iter().map(ToString::to_string).collect(); - args.push("--rustc-path".to_string()); - // This is a subtle/fragile thing. On rust-lang CI, there is no global - // `rustc`, and Cargo doesn't offer a convenient way to get the path to - // `rustc`. Fortunately bootstrap sets `RUSTC` for us, which is pointing - // to the stage0 compiler. - // - // Otherwise, if you are running compiletests's tests manually, you - // probably don't have `RUSTC` set, in which case this falls back to the - // global rustc. If your global rustc is too far out of sync with stage0, - // then this may cause confusing errors. Or if for some reason you don't - // have rustc in PATH, that would also fail. - args.push(std::env::var("RUSTC").unwrap_or_else(|_| { - eprintln!( - "warning: RUSTC not set, using global rustc (are you not running via bootstrap?)" - ); - "rustc".to_string() - })); - crate::parse_config(args) +#[derive(Default)] +struct ConfigBuilder { + channel: Option, + host: Option, + target: Option, + stage_id: Option, + llvm_version: Option, + git_hash: bool, + system_llvm: bool, +} + +impl ConfigBuilder { + fn channel(&mut self, s: &str) -> &mut Self { + self.channel = Some(s.to_owned()); + self + } + + fn host(&mut self, s: &str) -> &mut Self { + self.host = Some(s.to_owned()); + self + } + + fn target(&mut self, s: &str) -> &mut Self { + self.target = Some(s.to_owned()); + self + } + + fn stage_id(&mut self, s: &str) -> &mut Self { + self.stage_id = Some(s.to_owned()); + self + } + + fn llvm_version(&mut self, s: &str) -> &mut Self { + self.llvm_version = Some(s.to_owned()); + self + } + + fn git_hash(&mut self, b: bool) -> &mut Self { + self.git_hash = b; + self + } + + fn system_llvm(&mut self, s: bool) -> &mut Self { + self.system_llvm = s; + self + } + + fn build(&mut self) -> Config { + let args = &[ + "compiletest", + "--mode=ui", + "--suite=ui", + "--compile-lib-path=", + "--run-lib-path=", + "--python=", + "--jsondocck-path=", + "--src-base=", + "--build-base=", + "--sysroot-base=", + "--cc=c", + "--cxx=c++", + "--cflags=", + "--cxxflags=", + "--llvm-components=", + "--android-cross-path=", + "--stage-id", + self.stage_id.as_deref().unwrap_or("stage2-x86_64-unknown-linux-gnu"), + "--channel", + self.channel.as_deref().unwrap_or("nightly"), + "--host", + self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + "--target", + self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + ]; + let mut args: Vec = args.iter().map(ToString::to_string).collect(); + + if let Some(ref llvm_version) = self.llvm_version { + args.push("--llvm-version".to_owned()); + args.push(llvm_version.clone()); + } + + if self.git_hash { + args.push("--git-hash".to_owned()); + } + if self.system_llvm { + args.push("--system-llvm".to_owned()); + } + + args.push("--rustc-path".to_string()); + // This is a subtle/fragile thing. On rust-lang CI, there is no global + // `rustc`, and Cargo doesn't offer a convenient way to get the path to + // `rustc`. Fortunately bootstrap sets `RUSTC` for us, which is pointing + // to the stage0 compiler. + // + // Otherwise, if you are running compiletests's tests manually, you + // probably don't have `RUSTC` set, in which case this falls back to the + // global rustc. If your global rustc is too far out of sync with stage0, + // then this may cause confusing errors. Or if for some reason you don't + // have rustc in PATH, that would also fail. + args.push(std::env::var("RUSTC").unwrap_or_else(|_| { + eprintln!( + "warning: RUSTC not set, using global rustc (are you not running via bootstrap?)" + ); + "rustc".to_string() + })); + crate::parse_config(args) + } +} + +fn cfg() -> ConfigBuilder { + ConfigBuilder::default() } fn parse_rs(config: &Config, contents: &str) -> EarlyProps { @@ -115,7 +185,7 @@ fn parse_makefile(config: &Config, contents: &str) -> EarlyProps { #[test] fn should_fail() { - let config = config(); + let config: Config = cfg().build(); let tn = test::DynTestName(String::new()); let p = Path::new("a.rs"); @@ -127,7 +197,7 @@ fn should_fail() { #[test] fn revisions() { - let config = config(); + let config: Config = cfg().build(); assert_eq!(parse_rs(&config, "// revisions: a b c").revisions, vec!["a", "b", "c"],); assert_eq!( @@ -138,7 +208,7 @@ fn revisions() { #[test] fn aux_build() { - let config = config(); + let config: Config = cfg().build(); assert_eq!( parse_rs( @@ -155,36 +225,31 @@ fn aux_build() { #[test] fn no_system_llvm() { - let mut config = config(); - - config.system_llvm = false; + let config: Config = cfg().system_llvm(false).build(); assert!(!check_ignore(&config, "// no-system-llvm")); - config.system_llvm = true; + let config: Config = cfg().system_llvm(true).build(); assert!(check_ignore(&config, "// no-system-llvm")); } #[test] fn llvm_version() { - let mut config = config(); - - config.llvm_version = Some(80102); + let config: Config = cfg().llvm_version("8.1.2").build(); assert!(check_ignore(&config, "// min-llvm-version: 9.0")); - config.llvm_version = Some(90001); + let config: Config = cfg().llvm_version("9.0.1").build(); assert!(check_ignore(&config, "// min-llvm-version: 9.2")); - config.llvm_version = Some(90301); + let config: Config = cfg().llvm_version("9.3.1").build(); assert!(!check_ignore(&config, "// min-llvm-version: 9.2")); - config.llvm_version = Some(100000); + let config: Config = cfg().llvm_version("10.0.0").build(); assert!(!check_ignore(&config, "// min-llvm-version: 9.0")); } #[test] fn ignore_target() { - let mut config = config(); - config.target = "x86_64-unknown-linux-gnu".to_owned(); + let config: Config = cfg().target("x86_64-unknown-linux-gnu").build(); assert!(check_ignore(&config, "// ignore-x86_64-unknown-linux-gnu")); assert!(check_ignore(&config, "// ignore-x86_64")); @@ -200,8 +265,7 @@ fn ignore_target() { #[test] fn only_target() { - let mut config = config(); - config.target = "x86_64-pc-windows-gnu".to_owned(); + let config: Config = cfg().target("x86_64-pc-windows-gnu").build(); assert!(check_ignore(&config, "// only-x86")); assert!(check_ignore(&config, "// only-linux")); @@ -217,8 +281,7 @@ fn only_target() { #[test] fn stage() { - let mut config = config(); - config.stage_id = "stage1-x86_64-unknown-linux-gnu".to_owned(); + let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build(); assert!(check_ignore(&config, "// ignore-stage1")); assert!(!check_ignore(&config, "// ignore-stage2")); @@ -226,18 +289,16 @@ fn stage() { #[test] fn cross_compile() { - let mut config = config(); - config.host = "x86_64-apple-darwin".to_owned(); - config.target = "wasm32-unknown-unknown".to_owned(); + let config: Config = cfg().host("x86_64-apple-darwin").target("wasm32-unknown-unknown").build(); assert!(check_ignore(&config, "// ignore-cross-compile")); - config.target = config.host.clone(); + let config: Config = cfg().host("x86_64-apple-darwin").target("x86_64-apple-darwin").build(); assert!(!check_ignore(&config, "// ignore-cross-compile")); } #[test] fn debugger() { - let mut config = config(); + let mut config = cfg().build(); config.debugger = None; assert!(!check_ignore(&config, "// ignore-cdb")); @@ -253,27 +314,24 @@ fn debugger() { #[test] fn git_hash() { - let mut config = config(); - config.git_hash = false; + let config: Config = cfg().git_hash(false).build(); assert!(check_ignore(&config, "// needs-git-hash")); - config.git_hash = true; + let config: Config = cfg().git_hash(true).build(); assert!(!check_ignore(&config, "// needs-git-hash")); } #[test] fn sanitizers() { - let mut config = config(); - // Target that supports all sanitizers: - config.target = "x86_64-unknown-linux-gnu".to_owned(); + let config: Config = cfg().target("x86_64-unknown-linux-gnu").build(); assert!(!check_ignore(&config, "// needs-sanitizer-address")); assert!(!check_ignore(&config, "// needs-sanitizer-leak")); assert!(!check_ignore(&config, "// needs-sanitizer-memory")); assert!(!check_ignore(&config, "// needs-sanitizer-thread")); // Target that doesn't support sanitizers: - config.target = "wasm32-unknown-emscripten".to_owned(); + let config: Config = cfg().target("wasm32-unknown-emscripten").build(); assert!(check_ignore(&config, "// needs-sanitizer-address")); assert!(check_ignore(&config, "// needs-sanitizer-leak")); assert!(check_ignore(&config, "// needs-sanitizer-memory")); @@ -291,8 +349,7 @@ fn asm_support() { ("i686-unknown-netbsd", true), ]; for (target, has_asm) in asms { - let mut config = config(); - config.target = target.to_string(); + let config = cfg().target(target).build(); assert_eq!(config.has_asm_support(), has_asm); assert_eq!(check_ignore(&config, "// needs-asm-support"), !has_asm) } @@ -300,8 +357,7 @@ fn asm_support() { #[test] fn channel() { - let mut config = config(); - config.channel = "beta".into(); + let config: Config = cfg().channel("beta").build(); assert!(check_ignore(&config, "// ignore-beta")); assert!(check_ignore(&config, "// only-nightly")); @@ -330,7 +386,7 @@ fn test_extract_version_range() { #[test] #[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")] fn test_duplicate_revisions() { - let config = config(); + let config: Config = cfg().build(); parse_rs(&config, "// revisions: rpass1 rpass1"); } @@ -345,8 +401,7 @@ fn ignore_arch() { ("thumbv7m-none-eabi", "thumb"), ]; for (target, arch) in archs { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert!(config.matches_arch(arch), "{target} {arch}"); assert!(check_ignore(&config, &format!("// ignore-{arch}"))); } @@ -361,8 +416,7 @@ fn matches_os() { ("x86_64-unknown-none", "none"), ]; for (target, os) in oss { - let mut config = config(); - config.target = target.to_string(); + let config = cfg().target(target).build(); assert!(config.matches_os(os), "{target} {os}"); assert!(check_ignore(&config, &format!("// ignore-{os}"))); } @@ -376,8 +430,7 @@ fn matches_env() { ("arm-unknown-linux-musleabi", "musl"), ]; for (target, env) in envs { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert!(config.matches_env(env), "{target} {env}"); assert!(check_ignore(&config, &format!("// ignore-{env}"))); } @@ -391,8 +444,7 @@ fn matches_abi() { ("arm-unknown-linux-gnueabi", "eabi"), ]; for (target, abi) in abis { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert!(config.matches_abi(abi), "{target} {abi}"); assert!(check_ignore(&config, &format!("// ignore-{abi}"))); } @@ -408,8 +460,7 @@ fn is_big_endian() { ("powerpc64-unknown-linux-gnu", true), ]; for (target, is_big) in endians { - let mut config = config(); - config.target = target.to_string(); + let config = cfg().target(target).build(); assert_eq!(config.is_big_endian(), is_big, "{target} {is_big}"); assert_eq!(check_ignore(&config, "// ignore-endian-big"), is_big); } @@ -424,8 +475,7 @@ fn pointer_width() { ("msp430-none-elf", 16), ]; for (target, width) in widths { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert_eq!(config.get_pointer_width(), width, "{target} {width}"); assert_eq!(check_ignore(&config, "// ignore-16bit"), width == 16); assert_eq!(check_ignore(&config, "// ignore-32bit"), width == 32); @@ -456,8 +506,7 @@ fn wasm_special() { ("wasm64-unknown-unknown", "wasm64", true), ]; for (target, pattern, ignore) in ignores { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert_eq!( check_ignore(&config, &format!("// ignore-{pattern}")), ignore, @@ -476,8 +525,7 @@ fn families() { ("wasm32-unknown-emscripten", "unix"), ]; for (target, family) in families { - let mut config = config(); - config.target = target.to_string(); + let config: Config = cfg().target(target).build(); assert!(config.matches_family(family)); let other = if family == "windows" { "unix" } else { "windows" }; assert!(!config.matches_family(other)); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 02648fe5c2944..8f9425eb07167 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -9,108 +9,6 @@ use tracing::*; #[cfg(test)] mod tests; -pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-apple-ios", - "aarch64-apple-ios-sim", - "aarch64-apple-ios-macabi", - "aarch64-unknown-fuchsia", - "aarch64-linux-android", - "aarch64-unknown-linux-gnu", - "arm-linux-androideabi", - "armv7-linux-androideabi", - "i686-linux-android", - "i686-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-apple-ios", - "x86_64-apple-ios-macabi", - "x86_64-unknown-fuchsia", - "x86_64-linux-android", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - "s390x-unknown-linux-gnu", -]; - -// FIXME(rcvalle): More targets are likely supported. -pub const CFI_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-unknown-fuchsia", - "aarch64-linux-android", - "aarch64-unknown-freebsd", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-fuchsia", - "x86_64-pc-solaris", - "x86_64-unknown-freebsd", - "x86_64-unknown-illumos", - "x86_64-unknown-linux-gnu", - "x86_64-unknown-linux-musl", - "x86_64-unknown-netbsd", -]; - -pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"]; - -pub const KASAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-unknown-none", - "riscv64gc-unknown-none-elf", - "riscv64imac-unknown-none-elf", - "x86_64-unknown-none", -]; - -pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[ - // FIXME: currently broken, see #88132 - // "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-apple-ios-macabi", - "x86_64-unknown-linux-gnu", - "s390x-unknown-linux-gnu", -]; - -pub const MSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-unknown-linux-gnu", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - "s390x-unknown-linux-gnu", -]; - -pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-apple-ios", - "aarch64-apple-ios-sim", - "aarch64-apple-ios-macabi", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-apple-ios", - "x86_64-apple-ios-macabi", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - "s390x-unknown-linux-gnu", -]; - -pub const HWASAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-linux-android", "aarch64-unknown-linux-gnu"]; - -pub const MEMTAG_SUPPORTED_TARGETS: &[&str] = - &["aarch64-linux-android", "aarch64-unknown-linux-gnu"]; - -pub const SHADOWCALLSTACK_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-android"]; - -pub const XRAY_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-linux-android", - "aarch64-unknown-linux-gnu", - "aarch64-unknown-linux-musl", - "x86_64-linux-android", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - "x86_64-unknown-linux-musl", - "x86_64-unknown-netbsd", - "x86_64-unknown-none-linuxkernel", - "x86_64-unknown-openbsd", -]; - -pub const SAFESTACK_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - pub fn make_new_path(path: &str) -> String { assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index 23e88844bd0b8..9821677a1226e 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.49" +version = "0.51.1" diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index 91d981462e816..dff2c5e467afa 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -1,5 +1,7 @@ +use std::env; +use std::error::Error; use std::fs; -use std::io::{self, Write}; +use std::io::{self, Read, Seek, Write}; use std::path::PathBuf; /// This is printed to the file before the rest of the contents. @@ -11,25 +13,20 @@ const PRELUDE: &str = r#"// This file is autogenerated. // ignore-tidy-filelength "#; -fn main() -> io::Result<()> { +fn main() -> Result<(), Box> { let mut path: PathBuf = - std::env::args_os().nth(1).expect("a path to the rust repository is required").into(); - path.push("library/std/src/sys/windows/c/windows_sys.lst"); + env::args_os().nth(1).expect("a path to the rust repository is required").into(); + path.push("library/std/src/sys/windows/c"); + env::set_current_dir(&path)?; - // Load the list of APIs - let buffer = fs::read_to_string(&path)?; - let names: Vec<&str> = buffer - .lines() - .filter_map(|line| { - let line = line.trim(); - if line.is_empty() || line.starts_with("//") { None } else { Some(line) } - }) - .collect(); + let info = windows_bindgen::bindgen(["--etc", "windows_sys.lst"])?; + println!("{info}"); - // Write the bindings to windows-sys.rs - let bindings = windows_bindgen::standalone_std(&names); - path.set_extension("rs"); - let mut f = std::fs::File::create(&path)?; + // add some gunk to the output file. + let mut f = fs::File::options().read(true).write(true).open("windows_sys.rs")?; + let mut bindings = String::new(); + f.read_to_string(&mut bindings)?; + f.seek(io::SeekFrom::Start(0))?; f.write_all(PRELUDE.as_bytes())?; f.write_all(bindings.as_bytes())?; diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs index b5e977b2637d8..da94e686f3824 100644 --- a/src/tools/lld-wrapper/src/main.rs +++ b/src/tools/lld-wrapper/src/main.rs @@ -4,8 +4,8 @@ //! two arguments the `` command line interface is used to process the remaining arguments. //! If no `-flavor` argument is present the flavor is determined by the executable name. //! -//! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to -//! make gcc/clang pass `-flavor ` as the first two arguments in the linker invocation +//! With `-Clink-self-contained=+linker` we have gcc or clang invoke rust-lld. Since there is no way +//! to make gcc/clang pass `-flavor ` as the first two arguments in the linker invocation //! and since Windows does not support symbolic links for files this wrapper is used in place of a //! symbolic link. It execs `../rust-lld -flavor ` by propagating the flavor argument //! obtained from the wrapper's name as the first two arguments. diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index bcbd44a5f38cc..f026b7fd10452 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: branches: - 'master' schedule: - - cron: '11 5 * * *' # At 5:11 UTC every day. + - cron: '44 4 * * *' # At 4:44 UTC every day. defaults: run: @@ -208,7 +208,7 @@ jobs: git push -u origin $BRANCH - name: Create Pull Request run: | - PR=$(gh pr create -B master --title 'Automatic sync from rustc' --body '' --label subtree-sync) + 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." diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 4e50b8fae81ce..40a4332cdb9c0 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -71,19 +71,12 @@ and you can (cross-)run the entire test suite using: MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test ``` -If your target doesn't support libstd, you can run miri with +If your target doesn't support libstd that should usually just work. However, if you are using a +custom target file, you might have to set `MIRI_NO_STD=1`. -``` -MIRI_NO_STD=1 MIRI_TEST_TARGET=thumbv7em-none-eabihf ./miri test tests/fail/alloc/no_global_allocator.rs -MIRI_NO_STD=1 ./miri run tests/pass/no_std.rs --target thumbv7em-none-eabihf -``` - -to avoid attempting (and failing) to build libstd. Note that almost no tests will pass -this way, but you can run individual tests. - -`./miri test FILTER` only runs those tests that contain `FILTER` in their -filename (including the base directory, e.g. `./miri test fail` will run all -compile-fail tests). +`./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the +base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed +to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`. You can get a trace of which MIR statements are being executed by setting the `MIRI_LOG` environment variable. For example: diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index ca5b6d225154e..e654932255ae6 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,30 +19,38 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] [[package]] -name = "anyhow" -version = "1.0.71" +name = "annotate-snippets" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36" +dependencies = [ + "unicode-width", + "yansi-term", +] [[package]] -name = "atty" -version = "0.2.14" +name = "ansi_term" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "hermit-abi 0.1.19", - "libc", "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "autocfg" version = "1.1.0" @@ -51,9 +59,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -70,32 +78,37 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bstr" -version = "1.4.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", - "once_cell", "regex-automata", "serde", ] [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -116,9 +129,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -155,13 +171,32 @@ dependencies = [ [[package]] name = "colored" -version = "2.0.0" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ - "atty", + "is-terminal", "lazy_static", - "winapi", + "windows-sys 0.48.0", +] + +[[package]] +name = "comma" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" + +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", ] [[package]] @@ -176,37 +211,37 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "ctrlc" -version = "3.2.5" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] -name = "diff" -version = "0.1.13" +name = "encode_unicode" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "env_logger" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "atty", "humantime", + "is-terminal", "log", "regex", "termcolor", @@ -214,9 +249,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -245,18 +280,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -265,24 +297,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "humantime" @@ -296,6 +319,19 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "indicatif" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "instant" version = "0.1.12" @@ -306,21 +342,21 @@ dependencies = [ ] [[package]] -name = "io-lifetimes" -version = "1.0.10" +name = "is-terminal" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "libc", + "hermit-abi", + "rustix", "windows-sys 0.48.0", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "lazy_static" @@ -328,11 +364,17 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "levenshtein" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" + [[package]] name = "libc" -version = "0.2.142" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libffi" @@ -355,25 +397,25 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -381,12 +423,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" @@ -404,9 +443,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" @@ -419,9 +458,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -450,30 +489,35 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags", + "bitflags 2.4.0", "cfg-if", "libc", - "static_assertions", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" -version = "0.30.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "owo-colors" @@ -481,6 +525,15 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "pad" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" +dependencies = [ + "unicode-width", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -517,9 +570,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "portable-atomic" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" [[package]] name = "ppv-lite86" @@ -527,11 +586,21 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettydiff" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff1fec61082821f8236cf6c0c14e8172b62ce8a72a0eedc30d3b247bb68dc11" +dependencies = [ + "ansi_term", + "pad", +] + [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -581,7 +650,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -590,31 +659,37 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustc-demangle" @@ -651,13 +726,12 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys 0.48.0", @@ -665,39 +739,39 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -706,9 +780,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -717,30 +791,24 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "static_assertions" -version = "1.1.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -749,40 +817,40 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -812,9 +880,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -843,18 +911,23 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.11.7" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21899b59f53717dfad29e4f46e5b21a200a1b6888ab86532a07cfc8b48dd78c" +checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d" dependencies = [ + "annotate-snippets", + "anyhow", "bstr", "cargo-platform", "cargo_metadata", "color-eyre", "colored", + "comma", "crossbeam-channel", - "diff", + "indicatif", "lazy_static", + "levenshtein", + "prettydiff", "regex", "rustc_version", "rustfix", @@ -865,9 +938,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "valuable" @@ -899,9 +978,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -927,7 +1006,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -947,17 +1026,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -968,9 +1047,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -980,9 +1059,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -992,9 +1071,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -1004,9 +1083,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -1016,9 +1095,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -1028,9 +1107,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -1040,6 +1119,15 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi", +] diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 2ae6f922e3a18..c911a153c1373 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -32,11 +32,11 @@ libc = "0.2" [target.'cfg(target_os = "linux")'.dependencies] libffi = "3.2.0" -libloading = "0.7" +libloading = "0.8" [dev-dependencies] colored = "2" -ui_test = "0.11.7" +ui_test = "0.21.1" 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/README.md b/src/tools/miri/README.md index cedc558ebb87f..ca2bb80bd26d3 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -362,7 +362,7 @@ Some of these are **unsound**, which means they can lead to Miri failing to detect cases of undefined behavior in a program. * `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag - is **unsound**. + is **unsound**. This flag is **deprecated**. * `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you can focus on other failures, but it means Miri can miss bugs in your program. Using this flag is **unsound**. @@ -478,8 +478,12 @@ Moreover, Miri recognizes some environment variables: * `MIRI_TEST_TARGET` (recognized by the test suite and the `./miri` script) indicates which target architecture to test against. `miri` and `cargo miri` accept the `--target` flag for the same purpose. -* `MIRI_NO_STD` (recognized by `cargo miri` and the test suite) makes sure that the target's - sysroot is built without libstd. This allows testing and running no_std programs. +* `MIRI_TEST_THREADS` (recognized by the test suite): set the number of threads to use for running tests. + By default the number of cores is used. +* `MIRI_NO_STD` (recognized by `cargo miri`) makes sure that the target's sysroot is built without + libstd. This allows testing and running no_std programs. + (Miri has a heuristic to detect no-std targets based on the target name; this environment variable + is only needed when that heuristic fails.) * `RUSTC_BLESS` (recognized by the test suite and `cargo-miri-test/run-test.py`): overwrite all `stderr` and `stdout` files instead of checking whether the output matches. * `MIRI_SKIP_UI_CHECKS` (recognized by the test suite): don't check whether the diff --git a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock b/src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock new file mode 100644 index 0000000000000..7bf23225ea5b4 --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/invalidate/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "invalidate" +version = "0.1.0" diff --git a/src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml b/src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml new file mode 100644 index 0000000000000..14cf0882f0b6c --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/invalidate/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "invalidate" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs b/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs new file mode 100644 index 0000000000000..fa8deb851c37b --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/invalidate/src/main.rs @@ -0,0 +1,4 @@ +fn main() { + // The end of the range is just chosen to make the benchmark run for a few seconds. + for _ in 0..200_000 {} +} diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 1f3a33270e12f..c37a5ca88756f 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "bitflags" @@ -14,11 +14,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -38,18 +44,18 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" dependencies = [ "camino", "cargo-platform", @@ -61,9 +67,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -73,33 +82,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -114,73 +124,50 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" + +[[package]] +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -200,7 +187,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -209,7 +196,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -251,47 +238,46 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -300,9 +286,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -311,9 +297,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -322,31 +308,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -355,9 +341,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasi" @@ -365,156 +351,68 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index e118d12897a6a..55f6b5ac7efae 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -14,10 +14,10 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -directories = "4" +directories = "5" rustc_version = "0.4" serde_json = "1.0.40" -cargo_metadata = "0.15.0" +cargo_metadata = "0.18.0" rustc-build-sysroot = "0.4.1" # Enable some feature flags that dev-dependencies need but dependencies diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 80ce63255826e..d655df6d994d4 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -10,7 +10,7 @@ use rustc_version::VersionMeta; use crate::{setup::*, util::*}; -const CARGO_MIRI_HELP: &str = r#"Runs binary crates and tests in Miri +const CARGO_MIRI_HELP: &str = r"Runs binary crates and tests in Miri Usage: cargo miri [subcommand] [...] [--] [...] @@ -31,7 +31,7 @@ Examples: This will print the path to the generated sysroot (and nothing else) on stdout. stderr will still contain progress information about how the build is doing. -"#; +"; fn show_help() { println!("{CARGO_MIRI_HELP}"); diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index 77cecddcb8b14..d921741d5dec2 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -74,7 +74,17 @@ pub fn setup( } }; // Sysroot configuration and build details. - let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() { + let no_std = match std::env::var_os("MIRI_NO_STD") { + None => + // No-std heuristic taken from rust/src/bootstrap/config.rs + // (https://github.com/rust-lang/rust/blob/25b5af1b3a0b9e2c0c57b223b2d0e3e203869b2c/src/bootstrap/config.rs#L549-L555). + target.contains("-none") + || target.contains("nvptx") + || target.contains("switch") + || target.contains("-uefi"), + Some(val) => val != "0", + }; + let sysroot_config = if no_std { SysrootConfig::NoStd } else { SysrootConfig::WithStd { diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 9e7779e3513d9..1b3ed796c665b 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -112,7 +112,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings - MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture + MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std # no_std embedded architecture MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file ;; x86_64-apple-darwin) diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index 1a22596b7742a..6f8dd973fdd91 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "bitflags" @@ -14,6 +14,21 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -22,22 +37,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "directories" -version = "4.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] @@ -48,9 +64,30 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] [[package]] name = "getrandom" @@ -63,20 +100,35 @@ dependencies = [ "wasi", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "libc" -version = "0.2.144" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "linux-raw-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "miri-script" @@ -96,9 +148,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "path_macro" @@ -108,9 +166,9 @@ checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -130,7 +188,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -153,6 +211,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "same-file" version = "1.0.6" @@ -164,9 +235,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "shell-words" @@ -176,9 +247,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -187,18 +258,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -207,15 +278,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -229,13 +300,14 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix", ] [[package]] @@ -256,9 +328,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -269,17 +341,83 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "xshell" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90" +checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c" +checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e" diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml index d805a94c8f588..aaa788d58462d 100644 --- a/src/tools/miri/miri-script/Cargo.toml +++ b/src/tools/miri/miri-script/Cargo.toml @@ -13,11 +13,11 @@ edition = "2021" [dependencies] which = "4.4" walkdir = "2.3" -itertools = "0.10" +itertools = "0.11" path_macro = "1.0" shell-words = "1.1" anyhow = "1.0" xshell = "0.2" rustc_version = "0.4" dunce = "1.0.4" -directories = "4" +directories = "5" diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 124acc950986a..c24035ae0862d 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -37,7 +37,10 @@ impl MiriEnv { Err(_) => vec![], }; if !quiet { - eprintln!("$ (building Miri sysroot)"); + match self.sh.var("MIRI_TEST_TARGET") { + Ok(target) => eprintln!("$ (building Miri sysroot for {target})"), + Err(_) => eprintln!("$ (building Miri sysroot)"), + } } let output = cmd!(self.sh, "cargo +{toolchain} --quiet run {cargo_extra_flags...} --manifest-path {manifest_path} -- @@ -339,9 +342,9 @@ impl Command { "Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:" ); println!( - // Open PR with `subtree-sync` label to satisfy the `no-merges` triagebot check + // Open PR with `subtree update` title to silence the `no-merges` triagebot check // See https://github.com/rust-lang/rust/pull/114157 - " https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&labels=subtree-sync" + " https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&title=Miri+subtree+update" ); drop(josh); diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ab73f33497e9e..8f0a0a045abdb 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -366dab13f711df90a6891411458544199d159cbc +4ea5190026dbc1302b644d938e68bc6843cb8b24 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 1e9219d4bb23a..fc6151772a0fd 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -28,8 +28,9 @@ use rustc_middle::{ middle::exported_symbols::{ ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, }, - query::{ExternProviders, LocalCrate}, + query::LocalCrate, ty::TyCtxt, + util::Providers, }; use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; use rustc_session::search_paths::PathKind; @@ -43,11 +44,11 @@ struct MiriCompilerCalls { impl rustc_driver::Callbacks for MiriCompilerCalls { fn config(&mut self, config: &mut Config) { - config.override_queries = Some(|_, _, external_providers| { - external_providers.used_crate_source = |tcx, cnum| { - let mut providers = ExternProviders::default(); - rustc_metadata::provide_extern(&mut providers); - let mut crate_source = (providers.used_crate_source)(tcx, cnum); + config.override_queries = Some(|_, providers| { + providers.extern_queries.used_crate_source = |tcx, cnum| { + let mut providers = Providers::default(); + rustc_metadata::provide(&mut providers); + let mut crate_source = (providers.extern_queries.used_crate_source)(tcx, cnum); // HACK: rustc will emit "crate ... required to be available in rlib format, but // was not found in this form" errors once we use `tcx.dependency_formats()` if // there's no rlib provided, so setting a dummy path here to workaround those errors. @@ -125,7 +126,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { if config.opts.prints.is_empty() && self.target_crate { // Queries overridden here affect the data stored in `rmeta` files of dependencies, // which will be used later in non-`MIRI_BE_RUSTC` mode. - config.override_queries = Some(|_, local_providers, _| { + config.override_queries = Some(|_, local_providers| { // `exported_symbols` and `reachable_non_generics` provided by rustc always returns // an empty result if `tcx.sess.opts.output_types.should_codegen()` is false. local_providers.exported_symbols = |tcx, LocalCrate| { @@ -358,6 +359,10 @@ fn main() { since it is now enabled by default" ); } else if arg == "-Zmiri-disable-abi-check" { + eprintln!( + "WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.\n\ + If you have a use-case for it, please file an issue." + ); miri_config.check_abi = false; } else if arg == "-Zmiri-disable-isolation" { if matches!(isolation_enabled, Some(true)) { diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index b6dfd9944eef3..a95571572d684 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -66,10 +66,13 @@ pub struct FrameState { /// `stacked_borrows::GlobalState` upon function return, and if we attempt to pop a protected /// tag, to identify which call is responsible for protecting the tag. /// See `Stack::item_popped` for more explanation. + /// Tree Borrows also needs to know which allocation these tags + /// belong to so that it can perform a read through them immediately before + /// the frame gets popped. /// /// This will contain one tag per reference passed to the function, so /// a size of 2 is enough for the vast majority of functions. - pub protected_tags: SmallVec<[BorTag; 2]>, + pub protected_tags: SmallVec<[(AllocId, BorTag); 2]>, } impl VisitTags for FrameState { @@ -208,7 +211,7 @@ impl GlobalStateInner { } pub fn end_call(&mut self, frame: &machine::FrameExtra<'_>) { - for tag in &frame + for (_, tag) in &frame .borrow_tracker .as_ref() .expect("we should have borrow tracking data") @@ -305,7 +308,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -450,6 +456,19 @@ impl AllocState { AllocState::TreeBorrows(tb) => tb.borrow_mut().remove_unreachable_tags(tags), } } + + /// Tree Borrows needs to be told when a tag stops being protected. + pub fn release_protector<'tcx>( + &self, + machine: &MiriMachine<'_, 'tcx>, + global: &GlobalState, + tag: BorTag, + ) -> InterpResult<'tcx> { + match self { + AllocState::StackedBorrows(_sb) => Ok(()), + AllocState::TreeBorrows(tb) => tb.borrow_mut().release_protector(machine, global, tag), + } + } } impl VisitTags for AllocState { 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 9b0f13dd62c55..1a11879fa9012 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -1,6 +1,7 @@ use smallvec::SmallVec; use std::fmt; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::interpret::{alloc_range, AllocId, AllocRange, InterpError}; use rustc_span::{Span, SpanData}; use rustc_target::abi::Size; @@ -233,6 +234,12 @@ impl AllocHistory { protectors: SmallVec::new(), } } + + pub fn retain(&mut self, live_tags: &FxHashSet) { + self.invalidations.retain(|event| live_tags.contains(&event.tag)); + self.creations.retain(|event| live_tags.contains(&event.retag.new_tag)); + self.protectors.retain(|event| live_tags.contains(&event.tag)); + } } impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { @@ -429,6 +436,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { ProtectorKind::WeakProtector => "weakly protected", ProtectorKind::StrongProtector => "strongly protected", }; + let item_tag = item.tag(); let call_id = self .machine .threads @@ -437,7 +445,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { .map(|frame| { frame.extra.borrow_tracker.as_ref().expect("we should have borrow tracking data") }) - .find(|frame| frame.protected_tags.contains(&item.tag())) + .find(|frame| frame.protected_tags.iter().any(|(_, tag)| tag == &item_tag)) .map(|frame| frame.call_id) .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here? match self.operation { 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 a54bd32cd4097..66b729fb166b5 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -456,6 +456,7 @@ impl Stacks { stack.retain(live_tags); } } + self.history.retain(live_tags); self.modified_since_last_gc = false; } } @@ -718,7 +719,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' if let Some(protect) = new_perm.protector() { // See comment in `Stack::item_invalidated` for why we store the tag twice. - this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); + this.frame_mut() + .extra + .borrow_tracker + .as_mut() + .unwrap() + .protected_tags + .push((alloc_id, new_tag)); this.machine .borrow_tracker .as_mut() @@ -809,36 +816,43 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })) } - /// Retags an individual pointer, returning the retagged version. - /// `kind` indicates what kind of reference is being created. - fn sb_retag_reference( + fn sb_retag_place( &mut self, - val: &ImmTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, new_perm: NewPermission, info: RetagInfo, // diagnostics info about this retag - ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We want a place for where the ptr *points to*, so we get one. - let place = this.ref_to_mplace(val)?; - let size = this.size_and_align_of_mplace(&place)?.map(|(size, _)| size); + let size = this.size_and_align_of_mplace(place)?.map(|(size, _)| size); // FIXME: If we cannot determine the size (because the unsized tail is an `extern type`), // bail out -- we cannot reasonably figure out which memory range to reborrow. // See https://github.com/rust-lang/unsafe-code-guidelines/issues/276. let size = match size { Some(size) => size, - None => return Ok(val.clone()), + None => return Ok(place.clone()), }; // Compute new borrow. let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Reborrow. - let new_prov = this.sb_reborrow(&place, size, new_perm, new_tag, info)?; + let new_prov = this.sb_reborrow(place, size, new_perm, new_tag, info)?; - // Adjust pointer. - let new_place = place.map_provenance(|_| new_prov); + // Adjust place. + Ok(place.clone().map_provenance(|_| new_prov)) + } - // Return new pointer. + /// Retags an individual pointer, returning the retagged version. + /// `kind` indicates what kind of reference is being created. + fn sb_retag_reference( + &mut self, + val: &ImmTy<'tcx, Provenance>, + new_perm: NewPermission, + info: RetagInfo, // diagnostics info about this retag + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let place = this.ref_to_mplace(val)?; + let new_place = this.sb_retag_place(&place, new_perm, info)?; Ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) } } @@ -971,26 +985,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// call. /// /// This is used to ensure soundness of in-place function argument/return passing. - fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn sb_protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We have to turn the place into a pointer to use the usual retagging logic. - // (The pointer type does not matter, so we use a raw pointer.) - let ptr = this.mplace_to_ref(place)?; - // Reborrow it. With protection! That is the entire point. + // Retag it. With protection! That is the entire point. let new_perm = NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - let _new_ptr = this.sb_retag_reference( - &ptr, + this.sb_retag_place( + place, new_perm, RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false }, - )?; - // We just throw away `new_ptr`, so nobody can access this memory while it is protected. - - Ok(()) + ) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. 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 fd45671ba29d8..b3001b5b88cdc 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -19,6 +19,7 @@ pub enum AccessCause { Explicit(AccessKind), Reborrow, Dealloc, + FnExit, } impl fmt::Display for AccessCause { @@ -27,6 +28,7 @@ impl fmt::Display for AccessCause { Self::Explicit(kind) => write!(f, "{kind}"), Self::Reborrow => write!(f, "reborrow"), Self::Dealloc => write!(f, "deallocation"), + Self::FnExit => write!(f, "protector release"), } } } @@ -38,6 +40,7 @@ impl AccessCause { Self::Explicit(kind) => format!("{rel} {kind}"), Self::Reborrow => format!("reborrow (acting as a {rel} read access)"), Self::Dealloc => format!("deallocation (acting as a {rel} write access)"), + Self::FnExit => format!("protector release (acting as a {rel} read access)"), } } } @@ -52,7 +55,9 @@ pub struct Event { /// Relative position of the tag to the one used for the access. pub is_foreign: bool, /// User-visible range of the access. - pub access_range: AllocRange, + /// `None` means that this is an implicit access to the entire allocation + /// (used for the implicit read on protector release). + pub access_range: Option, /// The transition recorded by this event only occured on a subrange of /// `access_range`: a single access on `access_range` triggers several events, /// each with their own mutually disjoint `transition_range`. No-op transitions @@ -123,7 +128,17 @@ impl HistoryData { // NOTE: `transition_range` is explicitly absent from the error message, it has no significance // to the user. The meaningful one is `access_range`. let access = access_cause.print_as_access(is_foreign); - self.events.push((Some(span.data()), format!("{this} later transitioned to {endpoint} due to a {access} at offsets {access_range:?}", endpoint = transition.endpoint()))); + let access_range_text = match access_range { + Some(r) => format!("at offsets {r:?}"), + None => format!("on every location previously accessed by this tag"), + }; + self.events.push(( + Some(span.data()), + format!( + "{this} later transitioned to {endpoint} due to a {access} {access_range_text}", + endpoint = transition.endpoint() + ), + )); self.events .push((None, format!("this transition corresponds to {}", transition.summary()))); } @@ -745,7 +760,7 @@ const DEFAULT_FORMATTER: DisplayFmt = DisplayFmt { bot: '─', warning_text: "Warning: this tree is indicative only. Some tags may have been hidden.", }, - perm: DisplayFmtPermission { open: "|", sep: "|", close: "|", uninit: "---", range_sep: ".." }, + perm: DisplayFmtPermission { open: "|", sep: "|", close: "|", uninit: "----", range_sep: ".." }, padding: DisplayFmtPadding { join_middle: "├", join_last: "└", diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/exhaustive.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/exhaustive.rs new file mode 100644 index 0000000000000..daf3590358fd9 --- /dev/null +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/exhaustive.rs @@ -0,0 +1,111 @@ +//! Exhaustive testing utilities. +//! (These are used in Tree Borrows `#[test]`s for thorough verification +//! of the behavior of the state machine of permissions, +//! but the contents of this file are extremely generic) +#![cfg(test)] + +pub trait Exhaustive: Sized { + fn exhaustive() -> Box>; +} + +macro_rules! precondition { + ($cond:expr) => { + if !$cond { + continue; + } + }; +} +pub(crate) use precondition; + +// Trivial impls of `Exhaustive` for the standard types with 0, 1 and 2 elements respectively. + +impl Exhaustive for ! { + fn exhaustive() -> Box> { + Box::new(std::iter::empty()) + } +} + +impl Exhaustive for () { + fn exhaustive() -> Box> { + Box::new(std::iter::once(())) + } +} + +impl Exhaustive for bool { + fn exhaustive() -> Box> { + Box::new(vec![true, false].into_iter()) + } +} + +// Some container impls for `Exhaustive`. + +impl Exhaustive for Option +where + T: Exhaustive + 'static, +{ + fn exhaustive() -> Box> { + Box::new(std::iter::once(None).chain(T::exhaustive().map(Some))) + } +} + +impl Exhaustive for (T1, T2) +where + T1: Exhaustive + Clone + 'static, + T2: Exhaustive + 'static, +{ + fn exhaustive() -> Box> { + Box::new(T1::exhaustive().flat_map(|t1| T2::exhaustive().map(move |t2| (t1.clone(), t2)))) + } +} + +impl Exhaustive for [T; 1] +where + T: Exhaustive + 'static, +{ + fn exhaustive() -> Box> { + Box::new(T::exhaustive().map(|t| [t])) + } +} + +impl Exhaustive for [T; 2] +where + T: Exhaustive + Clone + 'static, +{ + fn exhaustive() -> Box> { + Box::new(T::exhaustive().flat_map(|t1| T::exhaustive().map(move |t2| [t1.clone(), t2]))) + } +} + +impl Exhaustive for [T; 3] +where + T: Exhaustive + Clone + 'static, +{ + fn exhaustive() -> Box> { + Box::new( + <[T; 2]>::exhaustive() + .flat_map(|[t1, t2]| T::exhaustive().map(move |t3| [t1.clone(), t2.clone(), t3])), + ) + } +} + +impl Exhaustive for [T; 4] +where + T: Exhaustive + Clone + 'static, +{ + fn exhaustive() -> Box> { + Box::new(<[T; 2]>::exhaustive().flat_map(|[t1, t2]| { + <[T; 2]>::exhaustive().map(move |[t3, t4]| [t1.clone(), t2.clone(), t3, t4]) + })) + } +} + +impl Exhaustive for [T; 5] +where + T: Exhaustive + Clone + 'static, +{ + fn exhaustive() -> Box> { + Box::new(<[T; 2]>::exhaustive().flat_map(|[t1, t2]| { + <[T; 3]>::exhaustive().map(move |[t3, t4, t5]| [t1.clone(), t2.clone(), t3, t4, t5]) + })) + } +} 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 8dd925a0ad80a..6d4c573a35c01 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -2,10 +2,16 @@ use log::trace; use rustc_target::abi::{Abi, Align, Size}; -use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind, RetagFields}; +use crate::borrow_tracker::{ + AccessKind, GlobalState, GlobalStateInner, ProtectorKind, RetagFields, +}; use rustc_middle::{ mir::{Mutability, RetagKind}, - ty::{self, layout::HasParamEnv, Ty}, + ty::{ + self, + layout::{HasParamEnv, HasTyCtxt}, + Ty, + }, }; use rustc_span::def_id::DefId; @@ -15,6 +21,10 @@ pub mod diagnostics; mod perms; mod tree; mod unimap; + +#[cfg(test)] +mod exhaustive; + use perms::Permission; pub use tree::Tree; @@ -62,7 +72,7 @@ impl<'tcx> Tree { self.perform_access( access_kind, tag, - range, + Some(range), global, span, diagnostics::AccessCause::Explicit(access_kind), @@ -91,6 +101,29 @@ impl<'tcx> Tree { pub fn expose_tag(&mut self, _tag: BorTag) { // TODO } + + /// A tag just lost its protector. + /// + /// This emits a special kind of access that is only applied + /// to initialized locations, as a protection against other + /// tags not having been made aware of the existence of this + /// protector. + pub fn release_protector( + &mut self, + machine: &MiriMachine<'_, 'tcx>, + global: &GlobalState, + tag: BorTag, + ) -> InterpResult<'tcx> { + let span = machine.current_span(); + self.perform_access( + AccessKind::Read, + tag, + None, // no specified range because it occurs on the entire allocation + global, + span, + diagnostics::AccessCause::FnExit, + ) + } } /// Policy for a new borrow. @@ -170,6 +203,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' new_tag: BorTag, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); + // Make sure the new permission makes sense as the initial permission of a fresh tag. + assert!(new_perm.initial_state.is_initial()); // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). this.check_ptr_access_align( place.ptr(), @@ -238,7 +273,13 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // We register the protection in two different places. // This makes creating a protector slower, but checking whether a tag // is protected faster. - this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); + this.frame_mut() + .extra + .borrow_tracker + .as_mut() + .unwrap() + .protected_tags + .push((alloc_id, new_tag)); this.machine .borrow_tracker .as_mut() @@ -265,7 +306,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' tree_borrows.perform_access( AccessKind::Read, orig_tag, - range, + Some(range), this.machine.borrow_tracker.as_ref().unwrap(), this.machine.current_span(), diagnostics::AccessCause::Reborrow, @@ -277,36 +318,19 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // Also inform the data race model (but only if any bytes are actually affected). if range.size.bytes() > 0 { if let Some(data_race) = alloc_extra.data_race.as_ref() { - // We sometimes need to make it a write, since not all retags commute with reads! - // FIXME: Is that truly the semantics we want? Some optimizations are likely to be - // very unhappy without this. We'd tsill ge some UB just by picking a suitable - // interleaving, but wether UB happens can depend on whether a write occurs in the - // future... - let is_write = new_perm.initial_state.is_active() - || (new_perm.initial_state.is_reserved() && new_perm.protector.is_some()); - if is_write { - // Need to get mutable access to alloc_extra. - // (Cannot always do this as we can do read-only reborrowing on read-only allocations.) - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; - alloc_extra.data_race.as_mut().unwrap().write(alloc_id, range, machine)?; - } else { - data_race.read(alloc_id, range, &this.machine)?; - } + data_race.read(alloc_id, range, &this.machine)?; } } Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })) } - /// Retags an individual pointer, returning the retagged version. - fn tb_retag_reference( + fn tb_retag_place( &mut self, - val: &ImmTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, new_perm: NewPermission, - ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We want a place for where the ptr *points to*, so we get one. - let place = this.ref_to_mplace(val)?; // Determine the size of the reborrow. // For most types this is the entire size of the place, however @@ -315,7 +339,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // then we override the size to do a zero-length reborrow. let reborrow_size = match new_perm { NewPermission { zero_size: false, .. } => - this.size_and_align_of_mplace(&place)? + this.size_and_align_of_mplace(place)? .map(|(size, _)| size) .unwrap_or(place.layout.size), _ => Size::from_bytes(0), @@ -331,12 +355,21 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Compute the actual reborrow. - let new_prov = this.tb_reborrow(&place, reborrow_size, new_perm, new_tag)?; + let new_prov = this.tb_reborrow(place, reborrow_size, new_perm, new_tag)?; - // Adjust pointer. - let new_place = place.map_provenance(|_| new_prov); + // Adjust place. + Ok(place.clone().map_provenance(|_| new_prov)) + } - // Return new pointer. + /// Retags an individual pointer, returning the retagged version. + fn tb_retag_reference( + &mut self, + val: &ImmTy<'tcx, Provenance>, + new_perm: NewPermission, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let place = this.ref_to_mplace(val)?; + let new_place = this.tb_retag_place(&place, new_perm)?; Ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) } } @@ -485,22 +518,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// call. /// /// This is used to ensure soundness of in-place function argument/return passing. - fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn tb_protect_place( + &mut self, + place: &MPlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - // We have to turn the place into a pointer to use the usual retagging logic. - // (The pointer type does not matter, so we use a raw pointer.) - let ptr = this.mplace_to_ref(place)?; - // Reborrow it. With protection! That is the entire point. + // Retag it. With protection! That is the entire point. let new_perm = NewPermission { - initial_state: Permission::new_active(), + initial_state: Permission::new_reserved( + place.layout.ty.is_freeze(this.tcx(), this.param_env()), + ), zero_size: false, protector: Some(ProtectorKind::StrongProtector), }; - let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?; - // We just throw away `new_ptr`, so nobody can access this memory while it is protected. - - Ok(()) + this.tb_retag_place(place, new_perm) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. @@ -517,7 +549,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // if converting this alloc_id from a global to a local one // uncovers a non-supported `extern static`. let alloc_extra = this.get_alloc_extra(alloc_id)?; - trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}"); + trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}"); alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag); } AllocKind::Function | AllocKind::VTable | AllocKind::Dead => { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index dab216bc5b1c5..bf72e902993b4 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -6,13 +6,22 @@ use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness; use crate::borrow_tracker::AccessKind; /// The activation states of a pointer. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum PermissionPriv { /// represents: a local reference that has not yet been written to; /// allows: child reads, foreign reads, foreign writes if type is freeze; - /// rejects: child writes (Active), foreign writes (Disabled, except if type is not freeze). - /// special case: behaves differently when protected to adhere more closely to noalias - Reserved { ty_is_freeze: bool }, + /// affected by: child writes (becomes Active), + /// rejects: foreign writes (Disabled, except if type is not freeze). + /// + /// special case: behaves differently when protected, which is where `conflicted` + /// is relevant + /// - `conflicted` is set on foreign reads, + /// - `conflicted` must not be set on child writes (there is UB otherwise). + /// This is so that the behavior of `Reserved` adheres to the rules of `noalias`: + /// - foreign-read then child-write is UB due to `conflicted`, + /// - child-write then foreign-read is UB since child-write will activate and then + /// foreign-read disables a protected `Active`, which is UB. + Reserved { ty_is_freeze: bool, conflicted: bool }, /// represents: a unique pointer; /// allows: child reads, child writes; /// rejects: foreign reads (Frozen), foreign writes (Disabled). @@ -29,10 +38,11 @@ enum PermissionPriv { use PermissionPriv::*; impl PartialOrd for PermissionPriv { - /// PermissionPriv is ordered as follows: - /// - Reserved(_) < Active < Frozen < Disabled; - /// - different kinds of `Reserved` (with or without interior mutability) - /// are incomparable to each other. + /// PermissionPriv is ordered by the reflexive transitive closure of + /// `Reserved(conflicted=false) < Reserved(conflicted=true) < Active < Frozen < Disabled`. + /// `Reserved` that have incompatible `ty_is_freeze` are incomparable to each other. + /// This ordering matches the reachability by transitions, as asserted by the exhaustive test + /// `permissionpriv_partialord_is_reachability`. fn partial_cmp(&self, other: &Self) -> Option { use Ordering::*; Some(match (self, other) { @@ -43,11 +53,28 @@ impl PartialOrd for PermissionPriv { (_, Frozen) => Less, (Active, _) => Greater, (_, Active) => Less, - (Reserved { .. }, Reserved { .. }) => return None, + ( + Reserved { ty_is_freeze: f1, conflicted: c1 }, + Reserved { ty_is_freeze: f2, conflicted: c2 }, + ) => { + // No transition ever changes `ty_is_freeze`. + if f1 != f2 { + return None; + } + // `bool` is ordered such that `false <= true`, so this works as intended. + c1.cmp(c2) + } }) } } +impl PermissionPriv { + /// Check if `self` can be the initial state of a pointer. + fn is_initial(&self) -> bool { + matches!(self, Reserved { conflicted: false, .. } | Frozen) + } +} + /// This module controls how each permission individually reacts to an access. /// Although these functions take `protected` as an argument, this is NOT because /// we check protector violations here, but because some permissions behave differently @@ -59,30 +86,28 @@ mod transition { Some(match state { Disabled => return None, // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read - // accesses, since the data is not being mutated. Hence the `{ .. }` + // accesses, since the data is not being mutated. Hence the `{ .. }`. readable @ (Reserved { .. } | Active | Frozen) => readable, }) } - /// A non-child node was read-accessed: noop on non-protected Reserved, advance to Frozen otherwise. + /// A non-child node was read-accessed: keep `Reserved` but mark it as `conflicted` if it + /// is protected; invalidate `Active`. fn foreign_read(state: PermissionPriv, protected: bool) -> Option { - use Option::*; Some(match state { // Non-writeable states just ignore foreign reads. non_writeable @ (Frozen | Disabled) => non_writeable, // Writeable states are more tricky, and depend on whether things are protected. // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read // accesses, since the data is not being mutated. Hence the `{ .. }` - res @ Reserved { .. } => - if protected { - // Someone else read, make sure we won't write. - // We could make this `Disabled` but it doesn't look like we get anything out of that extra UB. - Frozen - } else { - // Before activation and without protectors, foreign reads are fine. - // That's the entire point of 2-phase borrows. - res - }, + + // Someone else read. To make sure we won't write before function exit, + // we set the "conflicted" flag, which will disallow writes while we are protected. + Reserved { ty_is_freeze, .. } if protected => + Reserved { ty_is_freeze, conflicted: true }, + // Before activation and without protectors, foreign reads are fine. + // That's the entire point of 2-phase borrows. + res @ Reserved { .. } => res, Active => if protected { // We wrote, someone else reads -- that's bad. @@ -98,8 +123,12 @@ mod transition { /// A child node was write-accessed: `Reserved` must become `Active` to obtain /// write permissions, `Frozen` and `Disabled` cannot obtain such permissions and produce UB. - fn child_write(state: PermissionPriv, _protected: bool) -> Option { + fn child_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { + // If the `conflicted` flag is set, then there was a foreign read during + // the function call that is still ongoing (still `protected`), + // this is UB (`noalias` violation). + Reserved { conflicted: true, .. } if protected => return None, // A write always activates the 2-phase borrow, even with interior // mutability Reserved { .. } | Active => Active, @@ -111,7 +140,8 @@ mod transition { /// non-protected interior mutable `Reserved` which stay the same. fn foreign_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { - cell @ Reserved { ty_is_freeze: false } if !protected => cell, + Reserved { .. } if protected => Disabled, + res @ Reserved { ty_is_freeze: false, .. } => res, _ => Disabled, }) } @@ -134,7 +164,7 @@ mod transition { /// Public interface to the state machine that controls read-write permissions. /// This is the "private `enum`" pattern. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd)] pub struct Permission { inner: PermissionPriv, } @@ -147,14 +177,20 @@ pub struct PermTransition { } impl Permission { + /// Check if `self` can be the initial state of a pointer. + pub fn is_initial(&self) -> bool { + self.inner.is_initial() + } + /// Default initial permission of the root of a new tree. + /// Must *only* be used for the root, this is not in general an "initial" permission! pub fn new_active() -> Self { Self { inner: Active } } /// Default initial permission of a reborrowed mutable reference. pub fn new_reserved(ty_is_freeze: bool) -> Self { - Self { inner: Reserved { ty_is_freeze } } + Self { inner: Reserved { ty_is_freeze, conflicted: false } } } /// Default initial permission of a reborrowed shared reference @@ -162,18 +198,6 @@ impl Permission { Self { inner: Frozen } } - pub fn is_active(self) -> bool { - matches!(self.inner, Active) - } - - pub fn is_reserved(self) -> bool { - matches!(self.inner, Reserved { .. }) - } - - pub fn is_frozen(self) -> bool { - matches!(self.inner, Frozen) - } - /// Apply the transition to the inner PermissionPriv. pub fn perform_access( kind: AccessKind, @@ -229,7 +253,12 @@ pub mod diagnostics { f, "{}", match self { - Reserved { .. } => "Reserved", + Reserved { ty_is_freeze: true, conflicted: false } => "Reserved", + Reserved { ty_is_freeze: true, conflicted: true } => "Reserved (conflicted)", + Reserved { ty_is_freeze: false, conflicted: false } => + "Reserved (interior mutable)", + Reserved { ty_is_freeze: false, conflicted: true } => + "Reserved (interior mutable, conflicted)", Active => "Active", Frozen => "Frozen", Disabled => "Disabled", @@ -257,11 +286,13 @@ pub mod diagnostics { // and also as `diagnostics::DisplayFmtPermission.uninit` otherwise // alignment will be incorrect. match self.inner { - Reserved { ty_is_freeze: true } => "Res", - Reserved { ty_is_freeze: false } => "Re*", - Active => "Act", - Frozen => "Frz", - Disabled => "Dis", + Reserved { ty_is_freeze: true, conflicted: false } => "Rs ", + Reserved { ty_is_freeze: true, conflicted: true } => "RsC ", + Reserved { ty_is_freeze: false, conflicted: false } => "RsM ", + Reserved { ty_is_freeze: false, conflicted: true } => "RsCM", + Active => "Act ", + Frozen => "Frz ", + Disabled => "Dis ", } } } @@ -269,15 +300,13 @@ pub mod diagnostics { impl PermTransition { /// Readable explanation of the consequences of an event. /// Fits in the sentence "This accessed caused {trans.summary()}". - /// - /// Important: for the purposes of this explanation, `Reserved` is considered - /// to have write permissions, because that's what the diagnostics care about - /// (otherwise `Reserved -> Frozen` would be considered a noop). pub fn summary(&self) -> &'static str { assert!(self.is_possible()); match (self.from, self.to) { (_, Active) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", + (Reserved { conflicted: false, .. }, Reserved { conflicted: true, .. }) => + "a temporary loss of write permissions until function exit", (Frozen, Disabled) => "a loss of read permissions", (_, Disabled) => "a loss of read and write permissions", (old, new) => @@ -292,7 +321,7 @@ pub mod diagnostics { /// Irrelevant events: /// - modifications of write permissions when the error is related to read permissions /// (on failed reads and protected `Frozen -> Disabled`, ignore `Reserved -> Active`, - /// `Reserved -> Frozen`, and `Active -> Frozen`) + /// `Reserved(conflicted=false) -> Reserved(conflicted=true)`, and `Active -> Frozen`) /// - all transitions for attempts to deallocate strongly protected tags /// /// # Panics @@ -303,8 +332,9 @@ pub mod diagnostics { /// (Reserved < Active < Frozen < Disabled); /// - between `self` and `err` the permission should also be increasing, /// so all permissions inside `err` should be greater than `self.1`; - /// - `Active` and `Reserved` cannot cause an error due to insufficient permissions, - /// so `err` cannot be a `ChildAccessForbidden(_)` of either of them; + /// - `Active` and `Reserved(conflicted=false)` cannot cause an error + /// due to insufficient permissions, so `err` cannot be a `ChildAccessForbidden(_)` + /// of either of them; /// - `err` should not be `ProtectedDisabled(Disabled)`, because the protected /// tag should not have been `Disabled` in the first place (if this occurs it means /// we have unprotected tags that become protected) @@ -324,23 +354,28 @@ pub mod diagnostics { (Frozen, Frozen) => true, (Active, Frozen) => true, (Disabled, Disabled) => true, + (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => + true, // A pointer being `Disabled` is a strictly stronger source of // errors than it being `Frozen`. If we try to access a `Disabled`, - // then where it became `Frozen` (or `Active`) is the least of our concerns for now. - (Active | Frozen, Disabled) => false, + // then where it became `Frozen` (or `Active` or `Reserved`) is the least + // of our concerns for now. + (Reserved { conflicted: true, .. } | Active | Frozen, Disabled) => false, + (Reserved { conflicted: true, .. }, Frozen) => false, // `Active` and `Reserved` have all permissions, so a // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, Reserved { .. }) => + (_, Active) | (_, Reserved { conflicted: false, .. }) => unreachable!("this permission cannot cause an error"), - // No transition has `Reserved` as its `.to` unless it's a noop. - (Reserved { .. }, _) => unreachable!("self is a noop transition"), + // No transition has `Reserved(conflicted=false)` as its `.to` unless it's a noop. + (Reserved { conflicted: false, .. }, _) => + unreachable!("self is a noop transition"), // All transitions produced in normal executions (using `apply_access`) // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that // the transition `self` applies to, so permissions found must be increasing // in the order `self.from < self.to <= insufficient.inner` - (Disabled, Frozen) => + (Active | Frozen | Disabled, Reserved { .. }) | (Disabled, Frozen) => unreachable!("permissions between self and err must be increasing"), } } @@ -350,25 +385,34 @@ pub mod diagnostics { // This eliminates transitions like `Reserved -> Active` // when the error is a `Frozen -> Disabled`. match (self.to, before_disabled.inner) { - // We absolutely want to know where it was activated. + // We absolutely want to know where it was activated/frozen/marked + // conflicted. (Active, Active) => true, - // And knowing where it became Frozen is also important. (Frozen, Frozen) => true, + (Reserved { conflicted: true, .. }, Reserved { conflicted: true, .. }) => + true, // If the error is a transition `Frozen -> Disabled`, then we don't really // care whether before that was `Reserved -> Active -> Frozen` or - // `Reserved -> Frozen` or even `Frozen` directly. + // `Frozen` directly. // The error will only show either - // - created as Frozen, then Frozen -> Disabled is forbidden - // - created as Reserved, later became Frozen, then Frozen -> Disabled is forbidden - // In both cases the `Reserved -> Active` part is inexistant or irrelevant. + // - created as Reserved { conflicted: false }, + // then Reserved { .. } -> Disabled is forbidden + // - created as Reserved { conflicted: false }, + // then Active -> Disabled is forbidden + // A potential `Reserved { conflicted: false } + // -> Reserved { conflicted: true }` is inexistant or irrelevant, + // and so is the `Reserved { conflicted: false } -> Active` (Active, Frozen) => false, + (Reserved { conflicted: true, .. }, _) => false, (_, Disabled) => unreachable!( "permission that results in Disabled should not itself be Disabled in the first place" ), - // No transition has `Reserved` as its `.to` unless it's a noop. - (Reserved { .. }, _) => unreachable!("self is a noop transition"), + // No transition has `Reserved { conflicted: false }` as its `.to` + // unless it's a noop. + (Reserved { conflicted: false, .. }, _) => + unreachable!("self is a noop transition"), // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, // so permissions found must be increasing in the order @@ -394,46 +438,49 @@ pub mod diagnostics { } } +#[cfg(test)] +impl Permission { + pub fn is_reserved_with_conflicted(&self, expected_conflicted: bool) -> bool { + match self.inner { + Reserved { conflicted, .. } => conflicted == expected_conflicted, + _ => false, + } + } +} + #[cfg(test)] mod propagation_optimization_checks { pub use super::*; - - mod util { - pub use super::*; - impl PermissionPriv { - /// Enumerate all states - pub fn all() -> impl Iterator { - vec![ - Active, - Reserved { ty_is_freeze: true }, - Reserved { ty_is_freeze: false }, - Frozen, - Disabled, - ] - .into_iter() - } + use crate::borrow_tracker::tree_borrows::exhaustive::{precondition, Exhaustive}; + + impl Exhaustive for PermissionPriv { + fn exhaustive() -> Box> { + Box::new( + vec![Active, Frozen, Disabled].into_iter().chain( + <[bool; 2]>::exhaustive() + .map(|[ty_is_freeze, conflicted]| Reserved { ty_is_freeze, conflicted }), + ), + ) } + } - impl Permission { - pub fn all() -> impl Iterator { - PermissionPriv::all().map(|inner| Self { inner }) - } + impl Exhaustive for Permission { + fn exhaustive() -> Box> { + Box::new(PermissionPriv::exhaustive().map(|inner| Self { inner })) } + } - impl AccessKind { - /// Enumerate all AccessKind. - pub fn all() -> impl Iterator { - use AccessKind::*; - [Read, Write].into_iter() - } + impl Exhaustive for AccessKind { + fn exhaustive() -> Box> { + use AccessKind::*; + Box::new(vec![Read, Write].into_iter()) } + } - impl AccessRelatedness { - /// Enumerate all relative positions - pub fn all() -> impl Iterator { - use AccessRelatedness::*; - [This, StrictChildAccess, AncestorAccess, DistantAccess].into_iter() - } + impl Exhaustive for AccessRelatedness { + fn exhaustive() -> Box> { + use AccessRelatedness::*; + Box::new(vec![This, StrictChildAccess, AncestorAccess, DistantAccess].into_iter()) } } @@ -442,16 +489,22 @@ mod propagation_optimization_checks { // Even if the protector has disappeared. fn all_transitions_idempotent() { use transition::*; - for old in PermissionPriv::all() { - for (old_protected, new_protected) in [(true, true), (true, false), (false, false)] { - for access in AccessKind::all() { - for rel_pos in AccessRelatedness::all() { - if let Some(new) = perform_access(access, rel_pos, old, old_protected) { - assert_eq!( - new, - perform_access(access, rel_pos, new, new_protected).unwrap() - ); - } + for old in PermissionPriv::exhaustive() { + for (old_protected, new_protected) in <(bool, bool)>::exhaustive() { + // Protector can't appear out of nowhere: either the permission was + // created with a protector (`old_protected = true`) and it then may + // or may not lose it (`new_protected = false`, resp. `new_protected = true`), + // or it didn't have one upon creation and never will + // (`old_protected = new_protected = false`). + // We thus eliminate from this test and all other tests + // the case where the tag is initially unprotected and later becomes protected. + precondition!(old_protected || !new_protected); + for (access, rel_pos) in <(AccessKind, AccessRelatedness)>::exhaustive() { + if let Some(new) = perform_access(access, rel_pos, old, old_protected) { + assert_eq!( + new, + perform_access(access, rel_pos, new, new_protected).unwrap() + ); } } } @@ -459,13 +512,16 @@ mod propagation_optimization_checks { } #[test] + #[rustfmt::skip] fn foreign_read_is_noop_after_foreign_write() { use transition::*; let old_access = AccessKind::Write; let new_access = AccessKind::Read; - for old in PermissionPriv::all() { - for (old_protected, new_protected) in [(true, true), (true, false), (false, false)] { - for rel_pos in AccessRelatedness::all().filter(|rel| rel.is_foreign()) { + for old in PermissionPriv::exhaustive() { + for [old_protected, new_protected] in <[bool; 2]>::exhaustive() { + precondition!(old_protected || !new_protected); + for rel_pos in AccessRelatedness::exhaustive() { + precondition!(rel_pos.is_foreign()); if let Some(new) = perform_access(old_access, rel_pos, old, old_protected) { assert_eq!( new, @@ -480,18 +536,44 @@ mod propagation_optimization_checks { #[test] // Check that all transitions are consistent with the order on PermissionPriv, // i.e. Reserved -> Active -> Frozen -> Disabled - fn access_transitions_progress_increasing() { - use transition::*; - for old in PermissionPriv::all() { - for protected in [true, false] { - for access in AccessKind::all() { - for rel_pos in AccessRelatedness::all() { - if let Some(new) = perform_access(access, rel_pos, old, protected) { - assert!(old <= new); + fn permissionpriv_partialord_is_reachability() { + let reach = { + let mut reach = rustc_data_structures::fx::FxHashSet::default(); + // One-step transitions + reflexivity + for start in PermissionPriv::exhaustive() { + reach.insert((start, start)); + for (access, rel) in <(AccessKind, AccessRelatedness)>::exhaustive() { + for prot in bool::exhaustive() { + if let Some(end) = transition::perform_access(access, rel, start, prot) { + reach.insert((start, end)); } } } } + // Transitive closure + let mut finished = false; + while !finished { + finished = true; + for [start, mid, end] in <[PermissionPriv; 3]>::exhaustive() { + if reach.contains(&(start, mid)) + && reach.contains(&(mid, end)) + && !reach.contains(&(start, end)) + { + finished = false; + reach.insert((start, end)); + } + } + } + reach + }; + // Check that it matches `<` + for [p1, p2] in <[PermissionPriv; 2]>::exhaustive() { + let le12 = p1 <= p2; + let reach12 = reach.contains(&(p1, p2)); + assert!( + le12 == reach12, + "`{p1} reach {p2}` ({reach12}) does not match `{p1} <= {p2}` ({le12})" + ); } } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 5abf13229bbcc..b63b0bdff1217 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -10,6 +10,8 @@ //! and the relative position of the access; //! - idempotency properties asserted in `perms.rs` (for optimizations) +use std::fmt; + use smallvec::SmallVec; use rustc_const_eval::interpret::InterpResult; @@ -26,8 +28,10 @@ use crate::borrow_tracker::tree_borrows::{ use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind}; use crate::*; +mod tests; + /// Data for a single *location*. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(super) struct LocationState { /// A location is initialized when it is child-accessed for the first time (and the initial /// retag initializes the location for the range covered by the type), and it then stays @@ -65,10 +69,25 @@ impl LocationState { self } + /// Check if the location has been initialized, i.e. if it has + /// ever been accessed through a child pointer. pub fn is_initialized(&self) -> bool { self.initialized } + /// Check if the state can exist as the initial permission of a pointer. + /// + /// Do not confuse with `is_initialized`, the two are almost orthogonal + /// as apart from `Active` which is not initial and must be initialized, + /// any other permission can have an arbitrary combination of being + /// initial/initialized. + /// FIXME: when the corresponding `assert` in `tree_borrows/mod.rs` finally + /// passes and can be uncommented, remove this `#[allow(dead_code)]`. + #[cfg_attr(not(test), allow(dead_code))] + pub fn is_initial(&self) -> bool { + self.permission.is_initial() + } + pub fn permission(&self) -> Permission { self.permission } @@ -172,6 +191,16 @@ impl LocationState { } } +impl fmt::Display for LocationState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.permission)?; + if !self.initialized { + write!(f, "?")?; + } + Ok(()) + } +} + /// Tree structure with both parents and children since we want to be /// able to traverse the tree efficiently in both directions. #[derive(Clone, Debug)] @@ -253,6 +282,113 @@ enum ContinueTraversal { SkipChildren, } +/// Stack of nodes left to explore in a tree traversal. +struct TreeVisitorStack { + /// Identifier of the original access. + initial: UniIndex, + /// Function to apply to each tag. + f_propagate: NodeApp, + /// Handler to add the required context to diagnostics. + err_builder: ErrHandler, + /// Mutable state of the visit: the tags left to handle. + /// Every tag pushed should eventually be handled, + /// and the precise order is relevant for diagnostics. + stack: Vec<(UniIndex, AccessRelatedness)>, +} + +impl TreeVisitorStack +where + NodeApp: Fn(NodeAppArgs<'_>) -> Result, + ErrHandler: Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, +{ + /// Apply the function to the current `tag`, and push its children + /// to the stack of future tags to visit. + fn exec_and_visit( + &mut self, + this: &mut TreeVisitor<'_>, + idx: UniIndex, + exclude: Option, + rel_pos: AccessRelatedness, + ) -> Result<(), OutErr> { + // 1. apply the propagation function + let node = this.nodes.get_mut(idx).unwrap(); + let recurse = + (self.f_propagate)(NodeAppArgs { node, perm: this.perms.entry(idx), rel_pos }) + .map_err(|error_kind| { + (self.err_builder)(ErrHandlerArgs { + error_kind, + conflicting_info: &this.nodes.get(idx).unwrap().debug_info, + accessed_info: &this.nodes.get(self.initial).unwrap().debug_info, + }) + })?; + let node = this.nodes.get(idx).unwrap(); + // 2. add the children to the stack for future traversal + if matches!(recurse, ContinueTraversal::Recurse) { + let general_child_rel = rel_pos.for_child(); + for &child in node.children.iter() { + // Some child might be excluded from here and handled separately, + // e.g. the initially accessed tag. + if Some(child) != exclude { + // We should still ensure that if we don't skip the initially accessed + // it will receive the proper `AccessRelatedness`. + let this_child_rel = if child == self.initial { + AccessRelatedness::This + } else { + general_child_rel + }; + self.stack.push((child, this_child_rel)); + } + } + } + Ok(()) + } + + fn new(initial: UniIndex, f_propagate: NodeApp, err_builder: ErrHandler) -> Self { + Self { initial, f_propagate, err_builder, stack: Vec::new() } + } + + /// Finish the exploration by applying `exec_and_visit` until + /// the stack is empty. + fn finish(&mut self, visitor: &mut TreeVisitor<'_>) -> Result<(), OutErr> { + while let Some((idx, rel_pos)) = self.stack.pop() { + self.exec_and_visit(visitor, idx, /* no children to exclude */ None, rel_pos)?; + } + Ok(()) + } + + /// Push all ancestors to the exploration stack in order of nearest ancestor + /// towards the top. + fn push_and_visit_strict_ancestors( + &mut self, + visitor: &mut TreeVisitor<'_>, + ) -> Result<(), OutErr> { + let mut path_ascend = Vec::new(); + // First climb to the root while recording the path + let mut curr = self.initial; + while let Some(ancestor) = visitor.nodes.get(curr).unwrap().parent { + path_ascend.push((ancestor, curr)); + curr = ancestor; + } + // Then descend: + // - execute f_propagate on each node + // - record children in visit + while let Some((ancestor, next_in_path)) = path_ascend.pop() { + // Explore ancestors in descending order. + // `next_in_path` is excluded from the recursion because it + // will be the `ancestor` of the next iteration. + // It also needs a different `AccessRelatedness` than the other + // children of `ancestor`. + self.exec_and_visit( + visitor, + ancestor, + Some(next_in_path), + AccessRelatedness::StrictChildAccess, + )?; + } + Ok(()) + } +} + impl<'tree> TreeVisitor<'tree> { // Applies `f_propagate` to every vertex of the tree top-down in the following order: first // all ancestors of `start`, then `start` itself, then children of `start`, then the rest. @@ -269,107 +405,40 @@ impl<'tree> TreeVisitor<'tree> { start: BorTag, f_propagate: impl Fn(NodeAppArgs<'_>) -> Result, err_builder: impl Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, - ) -> Result<(), OutErr> -where { - struct TreeVisitAux { - accessed_tag: UniIndex, - f_propagate: NodeApp, - err_builder: ErrHandler, - stack: Vec<(UniIndex, AccessRelatedness)>, - } - impl TreeVisitAux - where - NodeApp: Fn(NodeAppArgs<'_>) -> Result, - ErrHandler: Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, - { - fn pop(&mut self) -> Option<(UniIndex, AccessRelatedness)> { - self.stack.pop() - } - - /// Apply the function to the current `tag`, and push its children - /// to the stack of future tags to visit. - fn exec_and_visit( - &mut self, - this: &mut TreeVisitor<'_>, - tag: UniIndex, - exclude: Option, - rel_pos: AccessRelatedness, - ) -> Result<(), OutErr> { - // 1. apply the propagation function - let node = this.nodes.get_mut(tag).unwrap(); - let recurse = - (self.f_propagate)(NodeAppArgs { node, perm: this.perms.entry(tag), rel_pos }) - .map_err(|error_kind| { - (self.err_builder)(ErrHandlerArgs { - error_kind, - conflicting_info: &this.nodes.get(tag).unwrap().debug_info, - accessed_info: &this - .nodes - .get(self.accessed_tag) - .unwrap() - .debug_info, - }) - })?; - let node = this.nodes.get(tag).unwrap(); - // 2. add the children to the stack for future traversal - if matches!(recurse, ContinueTraversal::Recurse) { - let child_rel = rel_pos.for_child(); - for &child in node.children.iter() { - // some child might be excluded from here and handled separately - if Some(child) != exclude { - self.stack.push((child, child_rel)); - } - } - } - Ok(()) - } - } + ) -> Result<(), OutErr> { + let start_idx = self.tag_mapping.get(&start).unwrap(); + let mut stack = TreeVisitorStack::new(start_idx, f_propagate, err_builder); + stack.push_and_visit_strict_ancestors(&mut self)?; + // All (potentially zero) ancestors have been explored, + // it's time to explore the `start` tag. + stack.exec_and_visit( + &mut self, + start_idx, + /* no children to exclude */ None, + AccessRelatedness::This, + )?; + // Then finish with a normal DFS. + stack.finish(&mut self) + } + // Applies `f_propagate` to every non-child vertex of the tree (ancestors first). + // + // `f_propagate` should follow the following format: for a given `Node` it updates its + // `Permission` depending on the position relative to `start` (given by an + // `AccessRelatedness`). + // It outputs whether the tree traversal for this subree should continue or not. + fn traverse_nonchildren( + mut self, + start: BorTag, + f_propagate: impl Fn(NodeAppArgs<'_>) -> Result, + err_builder: impl Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr, + ) -> Result<(), OutErr> { let start_idx = self.tag_mapping.get(&start).unwrap(); - let mut stack = - TreeVisitAux { accessed_tag: start_idx, f_propagate, err_builder, stack: Vec::new() }; - { - let mut path_ascend = Vec::new(); - // First climb to the root while recording the path - let mut curr = start_idx; - while let Some(ancestor) = self.nodes.get(curr).unwrap().parent { - path_ascend.push((ancestor, curr)); - curr = ancestor; - } - // Then descend: - // - execute f_propagate on each node - // - record children in visit - while let Some((ancestor, next_in_path)) = path_ascend.pop() { - // Explore ancestors in descending order. - // `next_in_path` is excluded from the recursion because it - // will be the `ancestor` of the next iteration. - // It also needs a different `AccessRelatedness` than the other - // children of `ancestor`. - stack.exec_and_visit( - &mut self, - ancestor, - Some(next_in_path), - AccessRelatedness::StrictChildAccess, - )?; - } - }; - // All (potentially zero) ancestors have been explored, call f_propagate on start - stack.exec_and_visit(&mut self, start_idx, None, AccessRelatedness::This)?; - // up to this point we have never popped from `stack`, hence if the - // path to the root is `root = p(n) <- p(n-1)... <- p(1) <- p(0) = start` - // then now `stack` contains - // `[ ... ]`, - // all of which are for now unexplored. - // This is the starting point of a standard DFS which will thus - // explore all non-ancestors of `start` in the following order: - // - all descendants of `start`; - // - then the unexplored descendants of `parent(start)`; - // ... - // - until finally the unexplored descendants of `root`. - while let Some((tag, rel_pos)) = stack.pop() { - stack.exec_and_visit(&mut self, tag, None, rel_pos)?; - } - Ok(()) + let mut stack = TreeVisitorStack::new(start_idx, f_propagate, err_builder); + stack.push_and_visit_strict_ancestors(&mut self)?; + // We *don't* visit the `start` tag, and we don't push its children. + // Only finish the DFS with the cousins. + stack.finish(&mut self) } } @@ -453,7 +522,7 @@ impl<'tcx> Tree { self.perform_access( AccessKind::Write, tag, - access_range, + Some(access_range), global, span, diagnostics::AccessCause::Dealloc, @@ -491,6 +560,11 @@ impl<'tcx> Tree { /// Map the per-node and per-location `LocationState::perform_access` /// to each location of `access_range`, on every tag of the allocation. /// + /// If `access_range` is `None`, this is interpreted as the special + /// access that is applied on protector release: + /// - the access will be applied only to initialized locations of the allocation, + /// - and it will not be visible to children. + /// /// `LocationState::perform_access` will take care of raising transition /// errors and updating the `initialized` status of each location, /// this traversal adds to that: @@ -501,56 +575,105 @@ impl<'tcx> Tree { &mut self, access_kind: AccessKind, tag: BorTag, - access_range: AllocRange, + access_range: Option, global: &GlobalState, span: Span, // diagnostics access_cause: diagnostics::AccessCause, // diagnostics ) -> InterpResult<'tcx> { - for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) { - TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } - .traverse_parents_this_children_others( - tag, - |args: NodeAppArgs<'_>| -> Result { - let NodeAppArgs { node, mut perm, rel_pos } = args; + use std::ops::Range; + // Performs the per-node work: + // - insert the permission if it does not exist + // - perform the access + // - record the transition + // to which some optimizations are added: + // - skip the traversal of the children in some cases + // - do not record noop transitions + // + // `perms_range` is only for diagnostics (it is the range of + // the `RangeMap` on which we are currently working). + let node_app = |perms_range: Range, + args: NodeAppArgs<'_>| + -> Result { + let NodeAppArgs { node, mut perm, rel_pos } = args; + + let old_state = perm.or_insert(LocationState::new(node.default_initial_perm)); + + match old_state.skip_if_known_noop(access_kind, rel_pos) { + ContinueTraversal::SkipChildren => return Ok(ContinueTraversal::SkipChildren), + _ => {} + } - let old_state = - perm.or_insert_with(|| LocationState::new(node.default_initial_perm)); + let protected = global.borrow().protected_tags.contains_key(&node.tag); + let transition = old_state.perform_access(access_kind, rel_pos, protected)?; + + // Record the event as part of the history + if !transition.is_noop() { + node.debug_info.history.push(diagnostics::Event { + transition, + is_foreign: rel_pos.is_foreign(), + access_cause, + access_range, + transition_range: perms_range.clone(), + span, + }); + } + Ok(ContinueTraversal::Recurse) + }; - match old_state.skip_if_known_noop(access_kind, rel_pos) { - ContinueTraversal::SkipChildren => - return Ok(ContinueTraversal::SkipChildren), - _ => {} - } + // Error handler in case `node_app` goes wrong. + // Wraps the faulty transition in more context for diagnostics. + let err_handler = |perms_range: Range, + args: ErrHandlerArgs<'_, TransitionError>| + -> InterpError<'tcx> { + let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args; + TbError { + conflicting_info, + access_cause, + error_offset: perms_range.start, + error_kind, + accessed_info, + } + .build() + }; - let protected = global.borrow().protected_tags.contains_key(&node.tag); - let transition = - old_state.perform_access(access_kind, rel_pos, protected)?; - - // Record the event as part of the history - if !transition.is_noop() { - node.debug_info.history.push(diagnostics::Event { - transition, - is_foreign: rel_pos.is_foreign(), - access_cause, - access_range, - transition_range: perms_range.clone(), - span, - }); - } - Ok(ContinueTraversal::Recurse) - }, - |args: ErrHandlerArgs<'_, TransitionError>| -> InterpError<'tcx> { - let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args; - TbError { - conflicting_info, - access_cause, - error_offset: perms_range.start, - error_kind, - accessed_info, - } - .build() - }, - )?; + if let Some(access_range) = access_range { + // Default branch: this is a "normal" access through a known range. + // We iterate over affected locations and traverse the tree for each of them. + for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) + { + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + .traverse_parents_this_children_others( + tag, + |args| node_app(perms_range.clone(), args), + |args| err_handler(perms_range.clone(), args), + )?; + } + } else { + // This is a special access through the entire allocation. + // It actually only affects `initialized` locations, so we need + // to filter on those before initiating the traversal. + // + // In addition this implicit access should not be visible to children, + // thus the use of `traverse_nonchildren`. + // See the test case `returned_mut_is_usable` from + // `tests/pass/tree_borrows/tree-borrows.rs` for an example of + // why this is important. + for (perms_range, perms) in self.rperms.iter_mut_all() { + let idx = self.tag_mapping.get(&tag).unwrap(); + // Only visit initialized permissions + if let Some(p) = perms.get(idx) && p.initialized { + TreeVisitor { + nodes: &mut self.nodes, + tag_mapping: &self.tag_mapping, + perms, + } + .traverse_nonchildren( + tag, + |args| node_app(perms_range.clone(), args), + |args| err_handler(perms_range.clone(), args), + )?; + } + } } Ok(()) } @@ -665,87 +788,3 @@ impl AccessRelatedness { } } } - -#[cfg(test)] -mod commutation_tests { - use super::*; - impl LocationState { - pub fn all() -> impl Iterator { - // We keep `latest_foreign_access` at `None` as that's just a cache. - Permission::all().flat_map(|permission| { - [false, true].into_iter().map(move |initialized| { - Self { permission, initialized, latest_foreign_access: None } - }) - }) - } - } - - #[test] - #[rustfmt::skip] - // Exhaustive check that for any starting configuration loc, - // for any two read accesses r1 and r2, if `loc + r1 + r2` is not UB - // and results in `loc'`, then `loc + r2 + r1` is also not UB and results - // in the same final state `loc'`. - // This lets us justify arbitrary read-read reorderings. - fn all_read_accesses_commute() { - let kind = AccessKind::Read; - // Two of the four combinations of `AccessRelatedness` are trivial, - // but we might as well check them all. - for rel1 in AccessRelatedness::all() { - for rel2 in AccessRelatedness::all() { - // Any protector state works, but we can't move reads across function boundaries - // so the two read accesses occur under the same protector. - for &protected in &[true, false] { - for loc in LocationState::all() { - // Apply 1 then 2. Failure here means that there is UB in the source - // and we skip the check in the target. - let mut loc12 = loc; - let Ok(_) = loc12.perform_access(kind, rel1, protected) else { continue }; - let Ok(_) = loc12.perform_access(kind, rel2, protected) else { continue }; - - // If 1 followed by 2 succeeded, then 2 followed by 1 must also succeed... - let mut loc21 = loc; - loc21.perform_access(kind, rel2, protected).unwrap(); - loc21.perform_access(kind, rel1, protected).unwrap(); - - // ... and produce the same final result. - assert_eq!( - loc12, loc21, - "Read accesses {:?} followed by {:?} do not commute !", - rel1, rel2 - ); - } - } - } - } - } - - #[test] - #[rustfmt::skip] - // Ensure that of 2 accesses happen, one foreign and one a child, and we are protected, that we - // get UB unless they are both reads. - fn protected_enforces_noalias() { - for rel1 in AccessRelatedness::all() { - for rel2 in AccessRelatedness::all() { - if rel1.is_foreign() == rel2.is_foreign() { - // We want to check pairs of accesses where one is foreign and one is not. - continue; - } - for kind1 in AccessKind::all() { - for kind2 in AccessKind::all() { - for mut state in LocationState::all() { - let protected = true; - let Ok(_) = state.perform_access(kind1, rel1, protected) else { continue }; - let Ok(_) = state.perform_access(kind2, rel2, protected) else { continue }; - // If these were both allowed, it must have been two reads. - assert!( - kind1 == AccessKind::Read && kind2 == AccessKind::Read, - "failed to enforce noalias between two accesses that are not both reads" - ); - } - } - } - } - } - } -} diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs new file mode 100644 index 0000000000000..35f3b53afdb47 --- /dev/null +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -0,0 +1,661 @@ +//! Tests for the tree +#![cfg(test)] + +use super::*; +use crate::borrow_tracker::tree_borrows::exhaustive::{precondition, Exhaustive}; +use std::fmt; + +impl Exhaustive for LocationState { + fn exhaustive() -> Box> { + // We keep `latest_foreign_access` at `None` as that's just a cache. + Box::new(<(Permission, bool)>::exhaustive().map(|(permission, initialized)| { + Self { permission, initialized, latest_foreign_access: None } + })) + } +} + +#[test] +#[rustfmt::skip] +// Exhaustive check that for any starting configuration loc, +// for any two read accesses r1 and r2, if `loc + r1 + r2` is not UB +// and results in `loc'`, then `loc + r2 + r1` is also not UB and results +// in the same final state `loc'`. +// This lets us justify arbitrary read-read reorderings. +fn all_read_accesses_commute() { + let kind = AccessKind::Read; + // Two of the four combinations of `AccessRelatedness` are trivial, + // but we might as well check them all. + for [rel1, rel2] in <[AccessRelatedness; 2]>::exhaustive() { + // Any protector state works, but we can't move reads across function boundaries + // so the two read accesses occur under the same protector. + for protected in bool::exhaustive() { + for loc in LocationState::exhaustive() { + // Apply 1 then 2. Failure here means that there is UB in the source + // and we skip the check in the target. + let mut loc12 = loc; + precondition!(loc12.perform_access(kind, rel1, protected).is_ok()); + precondition!(loc12.perform_access(kind, rel2, protected).is_ok()); + + // If 1 followed by 2 succeeded, then 2 followed by 1 must also succeed... + let mut loc21 = loc; + loc21.perform_access(kind, rel2, protected).unwrap(); + loc21.perform_access(kind, rel1, protected).unwrap(); + + // ... and produce the same final result. + assert_eq!( + loc12, loc21, + "Read accesses {:?} followed by {:?} do not commute !", + rel1, rel2 + ); + } + } + } +} + +#[test] +#[rustfmt::skip] +// Ensure that of 2 accesses happen, one foreign and one a child, and we are protected, that we +// get UB unless they are both reads. +fn protected_enforces_noalias() { + for [rel1, rel2] in <[AccessRelatedness; 2]>::exhaustive() { + // We want to check pairs of accesses where one is foreign and one is not. + precondition!(rel1.is_foreign() != rel2.is_foreign()); + for [kind1, kind2] in <[AccessKind; 2]>::exhaustive() { + for mut state in LocationState::exhaustive() { + let protected = true; + precondition!(state.perform_access(kind1, rel1, protected).is_ok()); + precondition!(state.perform_access(kind2, rel2, protected).is_ok()); + // If these were both allowed, it must have been two reads. + assert!( + kind1 == AccessKind::Read && kind2 == AccessKind::Read, + "failed to enforce noalias between two accesses that are not both reads" + ); + } + } + } +} + +/// We are going to exhaustively test the possibily of inserting +/// a spurious read in some code. +/// +/// We choose some pointer `x` through which we want a spurious read to be inserted. +/// `x` must thus be reborrowed, not have any children, and initially start protected. +/// +/// To check if inserting a spurious read is possible, we observe the behavior +/// of some pointer `y` different from `x` (possibly from a different thread, thus +/// the protectors on `x` and `y` are not necessarily well-nested). +/// It must be the case that no matter the context, the insertion of a spurious read +/// through `x` does not introduce UB in code that did not already have UB. +/// +/// Testing this will need some setup to simulate the evolution of the permissions +/// of `x` and `y` under arbitrary code. This arbitrary code of course includes +/// read and write accesses through `x` and `y`, but it must also consider +/// the less obvious: +/// - accesses through pointers that are *neither* `x` nor `y`, +/// - retags of `y` that change its relative position to `x`. +/// +/// +/// The general code pattern thus looks like +/// [thread 1] || [thread 2] +/// || y exists +/// retag x (protect) || +/// arbitrary code +/// read/write x/y/other +/// or retag y +/// or unprotect y +/// || +/// arbitrary code +/// read/write x/y/other +/// or retag y +/// or unprotect y +/// or unprotect x +/// +/// `x` must still be protected at the moment the spurious read is inserted +/// because spurious reads are impossible in general on unprotected tags. +mod spurious_read { + use super::*; + + /// Accessed pointer. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + enum PtrSelector { + X, + Y, + Other, + } + + /// Relative position of `x` and `y`. + /// `y` cannot be a child of `x` because `x` gets retagged as the first + /// thing in the pattern, so it cannot have children. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + enum RelPosXY { + MutuallyForeign, + /// X is a child of Y. + XChildY, + } + + impl Exhaustive for PtrSelector { + fn exhaustive() -> Box> { + use PtrSelector::*; + Box::new(vec![X, Y, Other].into_iter()) + } + } + + impl fmt::Display for PtrSelector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PtrSelector::X => write!(f, "x"), + PtrSelector::Y => write!(f, "y"), + PtrSelector::Other => write!(f, "z"), + } + } + } + + impl Exhaustive for RelPosXY { + fn exhaustive() -> Box> { + use RelPosXY::*; + Box::new(vec![MutuallyForeign, XChildY].into_iter()) + } + } + + impl fmt::Display for RelPosXY { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RelPosXY::MutuallyForeign => write!(f, "x and y are mutually foreign"), + RelPosXY::XChildY => write!(f, "x is a child of y"), + } + } + } + + impl PtrSelector { + /// Knowing the relative position of `x` to `y`, determine the relative + /// position of the accessed pointer defined by `self` relative to each `x` + /// and `y`. + /// + /// The output is not necessarily well-defined in general, but it + /// is unique when considered up to equivalence by `AccessRelatedness::is_foreign` + /// (e.g. having `RelPosXY::XChildY` and `PtrSelector::Other`, strictly + /// speaking it is impossible to determine if `Other` is a `DistantAccess` + /// or an `AncestorAccess` relative to `y`, but it doesn't really matter + /// because `DistantAccess.is_foreign() == AncestorAccess.is_foreign()`). + fn rel_pair(self, xy_rel: RelPosXY) -> (AccessRelatedness, AccessRelatedness) { + use AccessRelatedness::*; + match xy_rel { + RelPosXY::MutuallyForeign => + match self { + PtrSelector::X => (This, DistantAccess), + PtrSelector::Y => (DistantAccess, This), + PtrSelector::Other => (DistantAccess, DistantAccess), + }, + RelPosXY::XChildY => + match self { + PtrSelector::X => (This, StrictChildAccess), + PtrSelector::Y => (AncestorAccess, This), + PtrSelector::Other => (DistantAccess, DistantAccess), + }, + } + } + } + + /// Arbitrary access parametrized by the relative position of `x` and `y` + /// to each other. + #[derive(Debug, Clone, Copy)] + struct TestAccess { + ptr: PtrSelector, + kind: AccessKind, + } + + impl Exhaustive for TestAccess { + fn exhaustive() -> Box> { + Box::new( + <(PtrSelector, AccessKind)>::exhaustive() + .map(|(ptr, kind)| TestAccess { ptr, kind }), + ) + } + } + + impl fmt::Display for TestAccess { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let kind_text = match self.kind { + AccessKind::Read => "read", + AccessKind::Write => "write", + }; + write!(f, "{kind_text} {}", self.ptr) + } + } + + type AllowRet = (); + type NoRet = !; + #[derive(Clone)] + /// Events relevant to the evolution of 2 pointers are + /// - any access to the same location + /// - end of one of them being protected + /// - a retag that would change their relative position + /// The type `TestEvent` models these kinds of events. + /// + /// In order to prevent `x` or `y` from losing their protector, + /// choose a type `RetX` or `RetY` that is not inhabited. + /// e.g. + /// - `TestEvent` is any event including end of protector on either `x` or `y` + /// - `TestEvent` is any access + /// - `TestEvent` allows for `y` to lose its protector but not `x` + enum TestEvent { + Access(TestAccess), + RetX(RetX), + RetY(RetY), + /// The inner `LocStateProt` must be an initial state (as per the `is_initial` function) + RetagY(LocStateProt), + } + + impl Exhaustive for TestEvent + where + RetX: Exhaustive + 'static, + RetY: Exhaustive + 'static, + { + fn exhaustive() -> Box> { + Box::new( + ::exhaustive() + .map(|acc| Self::Access(acc)) + .chain(RetX::exhaustive().map(|retx| Self::RetX(retx))) + .chain(RetY::exhaustive().map(|rety| Self::RetY(rety))) + .chain( + LocStateProt::exhaustive() + .filter_map(|s| s.is_initial().then_some(Self::RetagY(s))), + ), + ) + } + } + + impl fmt::Display for TestEvent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TestEvent::Access(acc) => write!(f, "{acc}"), + // The fields of the `Ret` variants just serve to make them + // impossible to instanciate via the `RetX = NoRet` type; we can + // always ignore their value. + TestEvent::RetX(_) => write!(f, "ret x"), + TestEvent::RetY(_) => write!(f, "ret y"), + TestEvent::RetagY(newp) => write!(f, "retag y ({newp})"), + } + } + } + + #[derive(Clone, PartialEq, Eq, Hash)] + /// The state of a pointer on a location, including the protector. + /// It is represented here with the protector bound to the `LocationState` rather + /// than the `Map` as is normally the case, + /// but since all our exhaustive tests look at a single location + /// there's no risk of `prot` for different locations of the same tag getting + /// out of sync. + struct LocStateProt { + state: LocationState, + prot: bool, + } + + impl LocStateProt { + fn is_initial(&self) -> bool { + self.state.is_initial() + } + + fn perform_access(&self, kind: AccessKind, rel: AccessRelatedness) -> Result { + let mut state = self.state; + state.perform_access(kind, rel, self.prot).map_err(|_| ())?; + Ok(Self { state, prot: self.prot }) + } + + /// Remove the protector. + /// This does not perform the implicit read on function exit because + /// `LocStateProt` does not have enough context to apply its effect. + fn end_protector(&self) -> Self { + Self { prot: false, state: self.state } + } + } + + impl Exhaustive for LocStateProt { + fn exhaustive() -> Box> { + Box::new( + <(LocationState, bool)>::exhaustive().map(|(state, prot)| Self { state, prot }), + ) + } + } + + impl fmt::Display for LocStateProt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.state)?; + if self.prot { + write!(f, ", protect")?; + } + Ok(()) + } + } + + #[derive(Clone, PartialEq, Eq, Hash)] + /// The states of two pointers to the same location, + /// and their relationship to each other in the tree. + /// + /// Note that the two states interact: using one pointer can have + /// an impact on the other. + /// This makes `LocStateProtPair` more meaningful than a simple + /// `(LocStateProt, LocStateProt)` where the two states are not guaranteed + /// to be updated at the same time. + /// Some `LocStateProtPair` may be unreachable through normal means + /// such as `x: Active, y: Active` in the case of mutually foreign pointers. + struct LocStateProtPair { + xy_rel: RelPosXY, + x: LocStateProt, + y: LocStateProt, + } + + impl LocStateProtPair { + fn perform_test_access(self, acc: &TestAccess) -> Result { + let (xrel, yrel) = acc.ptr.rel_pair(self.xy_rel); + let x = self.x.perform_access(acc.kind, xrel)?; + let y = self.y.perform_access(acc.kind, yrel)?; + Ok(Self { x, y, ..self }) + } + + /// Perform a read on the given pointer if its state is `initialized`. + /// Must be called just after reborrowing a pointer, and just after + /// removing a protector. + fn read_if_initialized(self, ptr: PtrSelector) -> Result { + let initialized = match ptr { + PtrSelector::X => self.x.state.initialized, + PtrSelector::Y => self.y.state.initialized, + PtrSelector::Other => + panic!( + "the `initialized` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_initialized`" + ), + }; + if initialized { + self.perform_test_access(&TestAccess { ptr, kind: AccessKind::Read }) + } else { + Ok(self) + } + } + + /// Remove the protector of `x`, including the implicit read on function exit. + fn end_protector_x(self) -> Result { + let x = self.x.end_protector(); + Self { x, ..self }.read_if_initialized(PtrSelector::X) + } + + /// Remove the protector of `y`, including the implicit read on function exit. + fn end_protector_y(self) -> Result { + let y = self.y.end_protector(); + Self { y, ..self }.read_if_initialized(PtrSelector::Y) + } + + fn retag_y(self, new_y: LocStateProt) -> Result { + assert!(new_y.is_initial()); + // `xy_rel` changes to "mutually foreign" now: `y` can no longer be a parent of `x`. + Self { y: new_y, xy_rel: RelPosXY::MutuallyForeign, ..self } + .read_if_initialized(PtrSelector::Y) + } + + fn perform_test_event(self, evt: &TestEvent) -> Result { + match evt { + TestEvent::Access(acc) => self.perform_test_access(acc), + // The fields of the `Ret` variants just serve to make them + // impossible to instanciate via the `RetX = NoRet` type; we can + // always ignore their value. + TestEvent::RetX(_) => self.end_protector_x(), + TestEvent::RetY(_) => self.end_protector_y(), + TestEvent::RetagY(newp) => self.retag_y(newp.clone()), + } + } + } + + impl Exhaustive for LocStateProtPair { + fn exhaustive() -> Box> { + Box::new(<[LocStateProt; 2]>::exhaustive().flat_map(|[x, y]| { + RelPosXY::exhaustive() + .map(move |xy_rel| Self { x: x.clone(), y: y.clone(), xy_rel }) + })) + } + } + + impl fmt::Display for LocStateProtPair { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "x:{}, y:{}", self.x, self.y) + } + } + + /// Arbitrary sequence of events, as experienced by two mutually foreign pointers + /// to the same location. + #[derive(Clone)] + struct OpaqueCode { + events: Vec>, + } + + impl fmt::Display for OpaqueCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for evt in &self.events { + write!(f, "{evt}; ")?; + } + Ok(()) + } + } + + impl LocStateProtPair { + /// List all sequences of operations that start at `self` and do not cause UB + /// There are no duplicates: all sequences returned lead to distinct final states + /// (though the sequence is not guaranteed to be the shortest possible sequence of events). + /// Yields the states it reaches, and the sequence of operations that got us there. + fn all_states_reachable_via_opaque_code( + self, + ) -> impl Iterator)> + where + RetX: Exhaustive + Clone + 'static, + RetY: Exhaustive + Clone + 'static, + { + // We compute the reachable set of `Self` from `self` by non-UB `OpaqueCode`. + // Configurations are `(reach: Self, code: OpaqueCode)` tuples + // for which `code` applied to `self` returns `Ok(reach)`. + + // Stack of all configurations left to handle. + let mut handle: Vec<(Self, OpaqueCode<_, _>)> = + vec![(self, OpaqueCode { events: Vec::new() })]; + // Code that can be applied to `self`, and final state. + let mut paths: Vec<(Self, OpaqueCode<_, _>)> = Default::default(); + // Already explored states reachable from `self` + let mut seen: FxHashSet = Default::default(); + // This is essentially just computing the transitive closure by `perform_test_event`, + // most of the work lies in remembering the path up to the current state. + while let Some((state, path)) = handle.pop() { + for evt in >::exhaustive() { + if let Ok(next) = state.clone().perform_test_event(&evt) { + if seen.insert(next.clone()) { + let mut evts = path.clone(); + evts.events.push(evt); + paths.push((next.clone(), evts.clone())); + handle.push((next, evts)); + } + } + } + } + paths.into_iter() + } + } + + impl LocStateProtPair { + #[rustfmt::skip] + /// Two states (by convention `self` is the source and `other` is the target) + /// are "distinguishable" if there exists a sequence of instructions + /// that causes UB in the target but not in the source. + /// This implementation simply explores the reachable space + /// by all sequences of `TestEvent`. + /// This function can be instanciated with `RetX` and `RetY` + /// among `NoRet` or `AllowRet` to resp. forbid/allow `x`/`y` to lose their + /// protector. + fn distinguishable(&self, other: &Self) -> bool + where + RetX: Exhaustive + 'static, + RetY: Exhaustive + 'static, + { + if self == other { return false; } + let mut states = vec![(self.clone(), other.clone())]; + let mut seen = FxHashSet::default(); + while let Some(state) = states.pop() { + if !seen.insert(state.clone()) { continue; }; + let (source, target) = state; + for evt in >::exhaustive() { + // Generate successor states through events (accesses and protector ends) + let Ok(new_source) = source.clone().perform_test_event(&evt) else { continue; }; + let Ok(new_target) = target.clone().perform_test_event(&evt) else { return true; }; + if new_source == new_target { continue; } + states.push((new_source, new_target)); + } + } + false + } + } + + #[test] + // `Reserved(aliased=false)` and `Reserved(aliased=true)` are properly indistinguishable + // under the conditions where we want to insert a spurious read. + fn reserved_aliased_protected_indistinguishable() { + let source = LocStateProtPair { + xy_rel: RelPosXY::MutuallyForeign, + x: LocStateProt { + state: LocationState::new(Permission::new_frozen()).with_access(), + prot: true, + }, + y: LocStateProt { + state: LocationState::new(Permission::new_reserved(false)), + prot: true, + }, + }; + let acc = TestAccess { ptr: PtrSelector::X, kind: AccessKind::Read }; + let target = source.clone().perform_test_access(&acc).unwrap(); + assert!(source.y.state.permission.is_reserved_with_conflicted(false)); + assert!(target.y.state.permission.is_reserved_with_conflicted(true)); + assert!(!source.distinguishable::<(), ()>(&target)) + } + + #[derive(Clone, Debug)] + struct Pattern { + /// The relative position of `x` and `y` at the beginning of the arbitrary + /// code (i.e., just after `x` got created). + /// Might change during the execution if said arbitrary code contains any `retag y`. + xy_rel: RelPosXY, + /// Permission that `x` will be created as + /// (always protected until a possible `ret x` in the second phase). + /// This one should be initial (as per `is_initial`). + x_retag_perm: LocationState, + /// Permission that `y` has at the beginning of the pattern. + /// Can be any state, not necessarily initial + /// (since `y` exists already before the pattern starts). + /// This state might be reset during the execution if the opaque code + /// contains any `retag y`, but only to an initial state this time. + y_current_perm: LocationState, + /// Whether `y` starts with a protector. + /// Might change if the opaque code contains any `ret y`. + y_protected: bool, + } + + impl Exhaustive for Pattern { + fn exhaustive() -> Box> { + let mut v = Vec::new(); + for xy_rel in RelPosXY::exhaustive() { + for (x_retag_perm, y_current_perm) in <(LocationState, LocationState)>::exhaustive() + { + // We can only do spurious reads for initialized locations anyway. + precondition!(x_retag_perm.initialized); + // And `x` just got retagged, so it must be initial. + precondition!(x_retag_perm.permission.is_initial()); + for y_protected in bool::exhaustive() { + v.push(Pattern { xy_rel, x_retag_perm, y_current_perm, y_protected }); + } + } + } + Box::new(v.into_iter()) + } + } + + impl fmt::Display for Pattern { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (x, y) = self.retag_permissions(); + write!(f, "{}; ", self.xy_rel)?; + write!(f, "y: ({}); ", y,)?; + write!(f, "retag x ({}); ", x)?; + + write!(f, "; ;")?; + Ok(()) + } + } + + impl Pattern { + /// Return the permission that `y` starts as, and the permission that we + /// will retag `x` with. + /// This does not yet include a possible read-on-reborrow through `x`. + fn retag_permissions(&self) -> (LocStateProt, LocStateProt) { + let x = LocStateProt { state: self.x_retag_perm, prot: true }; + let y = LocStateProt { state: self.y_current_perm, prot: self.y_protected }; + (x, y) + } + + /// State that the pattern deterministically produces immediately after + /// the retag of `x`. + fn initial_state(&self) -> Result { + let (x, y) = self.retag_permissions(); + let state = LocStateProtPair { xy_rel: self.xy_rel, x, y }; + state.read_if_initialized(PtrSelector::X) + } + } + + #[test] + /// For each of the patterns described above, execute it once + /// as-is, and once with a spurious read inserted. Report any UB + /// in the target but not in the source. + fn test_all_patterns() { + let mut ok = 0; + let mut err = 0; + for pat in Pattern::exhaustive() { + let Ok(initial_source) = pat.initial_state() else { + // Failed to retag `x` in the source (e.g. `y` was protected Active) + continue; + }; + // `x` must stay protected, but the function protecting `y` might return here + for (final_source, opaque) in + initial_source.all_states_reachable_via_opaque_code::() + { + // Both executions are identical up to here. + // Now we do nothing in the source and in the target we do a spurious read. + // Then we check if the resulting states are distinguishable. + let distinguishable = { + assert!(final_source.x.prot); + let spurious_read = TestAccess { ptr: PtrSelector::X, kind: AccessKind::Read }; + if let Ok(final_target) = + final_source.clone().perform_test_access(&spurious_read) + { + // Only after the spurious read has been executed can `x` lose its + // protector. + final_source + .distinguishable::(&final_target) + .then_some(format!("{}", final_target)) + } else { + Some(format!("UB")) + } + }; + if let Some(final_target) = distinguishable { + eprintln!( + "For pattern '{}', inserting a spurious read through x makes the final state '{}' instead of '{}' which is observable", + pat, final_target, final_source + ); + eprintln!(" (arbitrary code instanciated with '{}')", opaque); + err += 1; + // We found an instanciation of the opaque code that makes this Pattern + // fail, we don't really need to check the rest. + break; + } + ok += 1; + } + } + if err > 0 { + panic!( + "Test failed after {}/{} patterns had UB in the target but not the source", + err, + ok + err + ) + } + } +} diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index 58af32385c507..d9cad9c8e0bd6 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -212,12 +212,9 @@ impl<'a, V> UniValMap { impl<'a, V> UniEntry<'a, V> { /// Insert in the map and get the value. - pub fn or_insert_with(&mut self, default: F) -> &mut V - where - F: FnOnce() -> V, - { + pub fn or_insert(&mut self, default: V) -> &mut V { if self.inner.is_none() { - *self.inner = Some(default()); + *self.inner = Some(default); } self.inner.as_mut().unwrap() } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 073b8b6a66130..24b9fa0776fb2 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -516,8 +516,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; // Atomics wrap around on overflow. - let val = this.binary_op(op, &old, rhs)?; - let val = if neg { this.unary_op(mir::UnOp::Not, &val)? } else { val }; + let val = this.wrapping_binary_op(op, &old, rhs)?; + let val = if neg { this.wrapping_unary_op(mir::UnOp::Not, &val)? } else { val }; this.allow_data_races_mut(|this| this.write_immediate(*val, place))?; this.validate_atomic_rmw(place, atomic)?; @@ -561,7 +561,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { this.validate_overlapping_atomic(place)?; let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; - let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; + let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; let new_val = if min { if lt { &old } else { &rhs } @@ -605,7 +605,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { // Read as immediate for the sake of `binary_op()` let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; // `binary_op` will bail if either of them is not a scalar. - let eq = this.binary_op(mir::BinOp::Eq, &old, expect_old)?; + let eq = this.wrapping_binary_op(mir::BinOp::Eq, &old, expect_old)?; // If the operation would succeed, but is "weak", fail some portion // of the time, based on `success_rate`. let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate; diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index ef4e7df3aba93..9041683fbc46b 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -803,8 +803,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if tcx.is_foreign_item(def_id) { throw_unsup_format!("foreign thread-local statics are not supported"); } - // We don't give a span -- statics don't need that, they cannot be generic or associated. - let allocation = this.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?; + let allocation = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; let mut allocation = allocation.inner().clone(); // This allocation will be deallocated when the thread dies, so it is not in read-only memory. allocation.mutability = Mutability::Mut; diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b05087134a0b2..4146a9b41ae1c 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1,5 +1,3 @@ -pub mod convert; - use std::cmp; use std::iter; use std::num::NonZeroUsize; @@ -962,7 +960,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.check_abi(abi, exp_abi)?; if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { // If compiler-builtins is providing the symbol, then don't treat it as a clash. - // We'll use our built-in implementation in `emulate_foreign_item_by_name` for increased + // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased // performance. Note that this means we won't catch any undefined behavior in // compiler-builtins when running other crates, but Miri can still be run on // compiler-builtins itself (or any crate that uses it as a normal dependency) @@ -1013,15 +1011,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn float_to_int_checked( &self, f: F, - dest_ty: Ty<'tcx>, + cast_to: TyAndLayout<'tcx>, round: rustc_apfloat::Round, - ) -> Option> + ) -> Option> where F: rustc_apfloat::Float + Into>, { let this = self.eval_context_ref(); - match dest_ty.kind() { + let val = match cast_to.ty.kind() { // Unsigned ty::Uint(t) => { let size = Integer::from_uint_ty(this, *t).size(); @@ -1033,11 +1031,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) { // Floating point value is NaN (flagged with INVALID_OP) or outside the range // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - None + return None; } else { // Floating point value can be represented by the integer type after rounding. // The INEXACT flag is ignored on purpose to allow rounding. - Some(Scalar::from_uint(res.value, size)) + Scalar::from_uint(res.value, size) } } // Signed @@ -1051,20 +1049,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) { // Floating point value is NaN (flagged with INVALID_OP) or outside the range // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - None + return None; } else { // Floating point value can be represented by the integer type after rounding. // The INEXACT flag is ignored on purpose to allow rounding. - Some(Scalar::from_int(res.value, size)) + Scalar::from_int(res.value, size) } } // Nothing else _ => span_bug!( this.cur_span(), - "attempted float-to-int conversion with non-int output type {dest_ty:?}" + "attempted float-to-int conversion with non-int output type {}", + cast_to.ty, ), - } + }; + Some(ImmTy::from_scalar(val, cast_to)) } /// Returns an integer type that is twice wide as `ty` diff --git a/src/tools/miri/src/helpers/convert.rs b/src/tools/miri/src/helpers/convert.rs deleted file mode 100644 index 4506fe47495d0..0000000000000 --- a/src/tools/miri/src/helpers/convert.rs +++ /dev/null @@ -1,49 +0,0 @@ -use implementations::NarrowerThan; - -/// Replacement for `as` casts going from wide integer to narrower integer. -/// -/// # Example -/// -/// ```ignore -/// let x = 99_u64; -/// let lo = x.truncate::(); -/// // lo is of type u16, equivalent to `x as u16`. -/// ``` -pub(crate) trait Truncate: Sized { - fn truncate(self) -> To - where - To: NarrowerThan, - { - NarrowerThan::truncate_from(self) - } -} - -impl Truncate for u16 {} -impl Truncate for u32 {} -impl Truncate for u64 {} -impl Truncate for u128 {} - -mod implementations { - pub(crate) trait NarrowerThan { - fn truncate_from(wide: T) -> Self; - } - - macro_rules! impl_narrower_than { - ($(NarrowerThan<{$($ty:ty),*}> for $self:ty)*) => { - $($( - impl NarrowerThan<$ty> for $self { - fn truncate_from(wide: $ty) -> Self { - wide as Self - } - } - )*)* - }; - } - - impl_narrower_than! { - NarrowerThan<{u128, u64, u32, u16}> for u8 - NarrowerThan<{u128, u64, u32}> for u16 - NarrowerThan<{u128, u64}> for u32 - NarrowerThan<{u128}> for u64 - } -} diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 816055cc4fe91..f1d8ce01bc24c 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,6 +8,7 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(round_ties_even)] +#![feature(let_chains)] #![feature(lint_reasons)] #![feature(trait_upcasting)] // Configure clippy and other lints @@ -86,9 +87,8 @@ pub use rustc_const_eval::interpret::*; // Resolve ambiguity. pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; -pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _}; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; -pub use crate::shims::foreign_items::EvalContextExt as _; +pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; pub use crate::shims::os_str::EvalContextExt as _; pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index ce7f47b5b4fee..930fa053d2091 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -707,11 +707,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { ); } "android" => { - // "signal" + // "signal" -- just needs a non-zero pointer value (function does not even get called), + // but we arrange for this to be callable anyway (it will then do nothing). let layout = this.machine.layouts.const_raw_ptr; - let dlsym = Dlsym::from_str("signal".as_bytes(), &this.tcx.sess.target.os)? - .expect("`signal` must be an actual dlsym on android"); - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal"))); let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout); Self::alloc_extern_static(this, "signal", val)?; // A couple zero-initialized pointer-sized extern statics. @@ -867,7 +866,7 @@ impl<'mir, 'tcx> MiriInterpCxExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> { /// Machine hook implementations. impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type MemoryKind = MiriMemoryKind; - type ExtraFnVal = Dlsym; + type ExtraFnVal = DynSym; type FrameExtra = FrameExtra<'tcx>; type AllocExtra = AllocExtra<'tcx>; @@ -939,15 +938,15 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn call_extra_fn( ecx: &mut MiriInterpCx<'mir, 'tcx>, - fn_val: Dlsym, + fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option, - _unwind: mir::UnwindAction, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - ecx.call_dlsym(fn_val, abi, &args, dest, ret) + ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind) } #[inline(always)] @@ -998,7 +997,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { bin_op: mir::BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> { ecx.binary_ptr_op(bin_op, left, right) } @@ -1275,19 +1274,25 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut InterpCx<'mir, 'tcx, Self>, place: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { - // We do need to write `uninit` so that even after the call ends, the former contents of - // this place cannot be observed any more. - ecx.write_uninit(place)?; // If we have a borrow tracker, we also have it set up protection so that all reads *and // writes* during this call are insta-UB. - if ecx.machine.borrow_tracker.is_some() { + let protected_place = if ecx.machine.borrow_tracker.is_some() { // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address. if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() { - ecx.protect_place(&place)?; + ecx.protect_place(&place)?.into() } else { // Locals that don't have their address taken are as protected as they can ever be. + place.clone() } - } + } else { + // No borrow tracker. + place.clone() + }; + // We do need to write `uninit` so that even after the call ends, the former contents of + // this place cannot be observed any more. We do the write after retagging so that for + // Tree Borrows, this is considered to activate the new tag. + ecx.write_uninit(&protected_place)?; + // Now we throw away the protected place, ensuring its tag is never used again. Ok(()) } @@ -1382,8 +1387,34 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ) -> InterpResult<'tcx> { // We want this *before* the return value copy, because the return place itself is protected // until we do `end_call` here. - if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().end_call(&frame.extra); + if let Some(global_borrow_tracker) = &ecx.machine.borrow_tracker { + // The body of this loop needs `global_borrow_tracker` immutably + // so we can't move this code inside the following `end_call`. + for (alloc_id, tag) in &frame + .extra + .borrow_tracker + .as_ref() + .expect("we should have borrow tracking data") + .protected_tags + { + // Just because the tag is protected doesn't guarantee that + // the allocation still exists (weak protectors allow deallocations) + // so we must check that the allocation exists. + // If it does exist, then we have the guarantee that the + // pointer is readable, and the implicit read access inserted + // will never cause UB on the pointer itself. + let (_, _, kind) = ecx.get_alloc_info(*alloc_id); + if matches!(kind, AllocKind::LiveData) { + let alloc_extra = ecx.get_alloc_extra(*alloc_id).unwrap(); + let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); + alloc_borrow_tracker.release_protector( + &ecx.machine, + global_borrow_tracker, + *tag, + )?; + } + } + global_borrow_tracker.borrow_mut().end_call(&frame.extra); } Ok(()) } diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index 368aa2bacdc8c..1faf8f9fc1228 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -1,6 +1,6 @@ use log::trace; -use rustc_middle::{mir, ty::Ty}; +use rustc_middle::mir; use rustc_target::abi::Size; use crate::*; @@ -11,7 +11,7 @@ pub trait EvalContextExt<'tcx> { bin_op: mir::BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)>; + ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)>; } impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> { @@ -20,7 +20,7 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> { bin_op: mir::BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> { use rustc_middle::mir::BinOp::*; trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right); @@ -50,7 +50,7 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> { Ge => left >= right, _ => bug!(), }; - (Scalar::from_bool(res), false, self.tcx.types.bool) + (ImmTy::from_bool(res, *self.tcx), false) } // Some more operations are possible with atomics. @@ -65,12 +65,16 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> { right.to_scalar().to_target_usize(self)?, self.machine.layouts.usize, ); - let (result, overflowing, _ty) = - self.overflowing_binary_op(bin_op, &left, &right)?; + let (result, overflowing) = self.overflowing_binary_op(bin_op, &left, &right)?; // Construct a new pointer with the provenance of `ptr` (the LHS). - let result_ptr = - Pointer::new(ptr.provenance, Size::from_bytes(result.to_target_usize(self)?)); - (Scalar::from_maybe_pointer(result_ptr, self), overflowing, left.layout.ty) + let result_ptr = Pointer::new( + ptr.provenance, + Size::from_bytes(result.to_scalar().to_target_usize(self)?), + ); + ( + ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, self), left.layout), + overflowing, + ) } _ => span_bug!(self.cur_span(), "Invalid operator on pointers: {:?}", bin_op), diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 836cab3ac9da8..ee2edd462d19e 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -88,10 +88,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_pointer(ptr, &place)?; } - this.write_immediate( - Immediate::new_slice(alloc.ptr(), len, this), - dest, - )?; + this.write_immediate(Immediate::new_slice(alloc.ptr(), len, this), dest)?; } // storage for pointers is allocated by the caller 1 => { diff --git a/src/tools/miri/src/shims/dlsym.rs b/src/tools/miri/src/shims/dlsym.rs deleted file mode 100644 index 8bf6d24f85f31..0000000000000 --- a/src/tools/miri/src/shims/dlsym.rs +++ /dev/null @@ -1,48 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::helpers::target_os_is_unix; -use crate::*; -use shims::unix::dlsym as unix; -use shims::windows::dlsym as windows; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - Posix(unix::Dlsym), - Windows(windows::Dlsym), -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &[u8], target_os: &str) -> InterpResult<'tcx, Option> { - let name = &*String::from_utf8_lossy(name); - Ok(match target_os { - target if target_os_is_unix(target) => - unix::Dlsym::from_str(name, target)?.map(Dlsym::Posix), - "windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows), - os => bug!("dlsym not implemented for target_os {}", os), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - match dlsym { - Dlsym::Posix(dlsym) => - unix::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - Dlsym::Windows(dlsym) => - windows::EvalContextExt::call_dlsym(this, dlsym, abi, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 0e8eaf450e43a..3462f03c30ffb 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -6,7 +6,7 @@ use rustc_apfloat::Float; use rustc_ast::expand::allocator::AllocatorKind; use rustc_hir::{ def::DefKind, - def_id::{CrateNum, DefId, LOCAL_CRATE}, + def_id::{CrateNum, LOCAL_CRATE}, }; use rustc_middle::middle::{ codegen_fn_attrs::CodegenFnAttrFlags, dependency_format::Linkage, @@ -22,123 +22,144 @@ use rustc_target::{ }; use super::backtrace::EvalContextExt as _; -use crate::helpers::{convert::Truncate, target_os_is_unix}; +use crate::helpers::target_os_is_unix; use crate::*; -/// Returned by `emulate_foreign_item_by_name`. -pub enum EmulateByNameResult<'mir, 'tcx> { +/// Type of dynamic symbols (for `dlsym` et al) +#[derive(Debug, Copy, Clone)] +pub struct DynSym(Symbol); + +#[allow(clippy::should_implement_trait)] +impl DynSym { + pub fn from_str(name: &str) -> Self { + DynSym(Symbol::intern(name)) + } +} + +/// Returned by `emulate_foreign_item_inner`. +pub enum EmulateForeignItemResult { /// The caller is expected to jump to the return block. NeedsJumping, /// Jumping has already been taken care of. AlreadyJumped, - /// A MIR body has been found for the function. - MirBody(&'mir mir::Body<'tcx>, ty::Instance<'tcx>), /// The item is not supported. NotSupported, } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - /// Returns the minimum alignment for the target architecture for allocations of the given size. - fn min_align(&self, size: u64, kind: MiriMemoryKind) -> Align { - let this = self.eval_context_ref(); - // List taken from `library/std/src/sys/common/alloc.rs`. - // This list should be kept in sync with the one from libstd. - let min_align = match this.tcx.sess.target.arch.as_ref() { - "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, - "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" => - 16, - arch => bug!("unsupported target architecture for malloc: `{}`", arch), + /// Emulates calling a foreign item, failing if the item is not supported. + /// This function will handle `goto_block` if needed. + /// Returns Ok(None) if the foreign item was completely handled + /// by this function. + /// Returns Ok(Some(body)) if processing the foreign item + /// is delegated to another function. + fn emulate_foreign_item( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { + let this = self.eval_context_mut(); + let tcx = this.tcx.tcx; + + // First: functions that diverge. + let ret = match ret { + None => + match link_name.as_str() { + "miri_start_panic" => { + // `check_shim` happens inside `handle_miri_start_panic`. + this.handle_miri_start_panic(abi, link_name, args, unwind)?; + return Ok(None); + } + // This matches calls to the foreign item `panic_impl`. + // The implementation is provided by the function with the `#[panic_handler]` attribute. + "panic_impl" => { + // We don't use `check_shim` here because we are just forwarding to the lang + // item. Argument count checking will be performed when the returned `Body` is + // called. + this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; + let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); + let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); + return Ok(Some(( + this.load_mir(panic_impl_instance.def, None)?, + panic_impl_instance, + ))); + } + #[rustfmt::skip] + | "exit" + | "ExitProcess" + => { + let exp_abi = if link_name.as_str() == "exit" { + Abi::C { unwind: false } + } else { + Abi::System { unwind: false } + }; + let [code] = this.check_shim(abi, exp_abi, link_name, args)?; + // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway + let code = this.read_scalar(code)?.to_i32()?; + throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); + } + "abort" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )) + } + _ => { + if let Some(body) = this.lookup_exported_symbol(link_name)? { + return Ok(Some(body)); + } + this.handle_unsupported(format!( + "can't call (diverging) foreign function: {link_name}" + ))?; + return Ok(None); + } + }, + Some(p) => p, }; - // Windows always aligns, even small allocations. - // Source: - // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big. - if kind == MiriMemoryKind::WinHeap || size >= min_align { - return Align::from_bytes(min_align).unwrap(); - } - // We have `size < min_align`. Round `size` *down* to the next power of two and use that. - fn prev_power_of_two(x: u64) -> u64 { - let next_pow2 = x.next_power_of_two(); - if next_pow2 == x { - // x *is* a power of two, just use that. - x - } else { - // x is between two powers, so next = 2*prev. - next_pow2 / 2 + + // Second: functions that return immediately. + match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { + EmulateForeignItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(dest)); + this.go_to_block(ret); } - } - Align::from_bytes(prev_power_of_two(size)).unwrap() - } + EmulateForeignItemResult::AlreadyJumped => (), + EmulateForeignItemResult::NotSupported => { + if let Some(body) = this.lookup_exported_symbol(link_name)? { + return Ok(Some(body)); + } - fn malloc( - &mut self, - size: u64, - zero_init: bool, - kind: MiriMemoryKind, - ) -> InterpResult<'tcx, Pointer>> { - let this = self.eval_context_mut(); - if size == 0 { - Ok(Pointer::null()) - } else { - let align = this.min_align(size, kind); - let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?; - if zero_init { - // We just allocated this, the access is definitely in-bounds and fits into our address space. - this.write_bytes_ptr( - ptr.into(), - iter::repeat(0u8).take(usize::try_from(size).unwrap()), - ) - .unwrap(); + this.handle_unsupported(format!( + "can't call foreign function `{link_name}` on OS `{os}`", + os = this.tcx.sess.target.os, + ))?; + return Ok(None); } - Ok(ptr.into()) } + + Ok(None) } - fn free( + /// Emulates a call to a `DynSym`. + fn emulate_dyn_sym( &mut self, - ptr: Pointer>, - kind: MiriMemoryKind, + sym: DynSym, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ret: Option, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - if !this.ptr_is_null(ptr)? { - this.deallocate_ptr(ptr, None, kind.into())?; - } + let res = self.emulate_foreign_item(sym.0, abi, args, dest, ret, unwind)?; + assert!(res.is_none(), "DynSyms that delegate are not supported"); Ok(()) } - fn realloc( - &mut self, - old_ptr: Pointer>, - new_size: u64, - kind: MiriMemoryKind, - ) -> InterpResult<'tcx, Pointer>> { - let this = self.eval_context_mut(); - let new_align = this.min_align(new_size, kind); - if this.ptr_is_null(old_ptr)? { - if new_size == 0 { - Ok(Pointer::null()) - } else { - let new_ptr = - this.allocate_ptr(Size::from_bytes(new_size), new_align, kind.into())?; - Ok(new_ptr.into()) - } - } else { - if new_size == 0 { - this.deallocate_ptr(old_ptr, None, kind.into())?; - Ok(Pointer::null()) - } else { - let new_ptr = this.reallocate_ptr( - old_ptr, - None, - Size::from_bytes(new_size), - new_align, - kind.into(), - )?; - Ok(new_ptr.into()) - } - } - } - /// Lookup the body of a function that has `link_name` as the symbol name. fn lookup_exported_symbol( &mut self, @@ -233,6 +254,78 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + fn malloc( + &mut self, + size: u64, + zero_init: bool, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx, Pointer>> { + let this = self.eval_context_mut(); + if size == 0 { + Ok(Pointer::null()) + } else { + let align = this.min_align(size, kind); + let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?; + if zero_init { + // We just allocated this, the access is definitely in-bounds and fits into our address space. + this.write_bytes_ptr( + ptr.into(), + iter::repeat(0u8).take(usize::try_from(size).unwrap()), + ) + .unwrap(); + } + Ok(ptr.into()) + } + } + + fn free( + &mut self, + ptr: Pointer>, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + if !this.ptr_is_null(ptr)? { + this.deallocate_ptr(ptr, None, kind.into())?; + } + Ok(()) + } + + fn realloc( + &mut self, + old_ptr: Pointer>, + new_size: u64, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx, Pointer>> { + let this = self.eval_context_mut(); + let new_align = this.min_align(new_size, kind); + if this.ptr_is_null(old_ptr)? { + if new_size == 0 { + Ok(Pointer::null()) + } else { + let new_ptr = + this.allocate_ptr(Size::from_bytes(new_size), new_align, kind.into())?; + Ok(new_ptr.into()) + } + } else { + if new_size == 0 { + this.deallocate_ptr(old_ptr, None, kind.into())?; + Ok(Pointer::null()) + } else { + let new_ptr = this.reallocate_ptr( + old_ptr, + None, + Size::from_bytes(new_size), + new_align, + kind.into(), + )?; + Ok(new_ptr.into()) + } + } + } +} + +impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Read bytes from a `(ptr, len)` argument fn read_byte_slice<'i>(&'i self, bytes: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, &'i [u8]> where @@ -246,115 +339,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(bytes) } - /// Emulates calling a foreign item, failing if the item is not supported. - /// This function will handle `goto_block` if needed. - /// Returns Ok(None) if the foreign item was completely handled - /// by this function. - /// Returns Ok(Some(body)) if processing the foreign item - /// is delegated to another function. - fn emulate_foreign_item( - &mut self, - def_id: DefId, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { - let this = self.eval_context_mut(); - let link_name = this.item_link_name(def_id); - let tcx = this.tcx.tcx; - - // First: functions that diverge. - let ret = match ret { - None => - match link_name.as_str() { - "miri_start_panic" => { - // `check_shim` happens inside `handle_miri_start_panic`. - this.handle_miri_start_panic(abi, link_name, args, unwind)?; - return Ok(None); - } - // This matches calls to the foreign item `panic_impl`. - // The implementation is provided by the function with the `#[panic_handler]` attribute. - "panic_impl" => { - // We don't use `check_shim` here because we are just forwarding to the lang - // item. Argument count checking will be performed when the returned `Body` is - // called. - this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; - let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); - let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); - return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, - panic_impl_instance, - ))); - } - #[rustfmt::skip] - | "exit" - | "ExitProcess" - => { - let exp_abi = if link_name.as_str() == "exit" { - Abi::C { unwind: false } - } else { - Abi::System { unwind: false } - }; - let [code] = this.check_shim(abi, exp_abi, link_name, args)?; - // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway - let code = this.read_scalar(code)?.to_i32()?; - throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); - } - "abort" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - this.handle_unsupported(format!( - "can't call (diverging) foreign function: {link_name}" - ))?; - return Ok(None); - } - }, - Some(p) => p, + /// Returns the minimum alignment for the target architecture for allocations of the given size. + fn min_align(&self, size: u64, kind: MiriMemoryKind) -> Align { + let this = self.eval_context_ref(); + // List taken from `library/std/src/sys/common/alloc.rs`. + // This list should be kept in sync with the one from libstd. + let min_align = match this.tcx.sess.target.arch.as_ref() { + "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, + "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" => + 16, + arch => bug!("unsupported target architecture for malloc: `{}`", arch), }; - - // Second: functions that return immediately. - match this.emulate_foreign_item_by_name(link_name, abi, args, dest)? { - EmulateByNameResult::NeedsJumping => { - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - } - EmulateByNameResult::AlreadyJumped => (), - EmulateByNameResult::MirBody(mir, instance) => return Ok(Some((mir, instance))), - EmulateByNameResult::NotSupported => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - - this.handle_unsupported(format!( - "can't call foreign function `{link_name}` on OS `{os}`", - os = this.tcx.sess.target.os, - ))?; - return Ok(None); + // Windows always aligns, even small allocations. + // Source: + // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big. + if kind == MiriMemoryKind::WinHeap || size >= min_align { + return Align::from_bytes(min_align).unwrap(); + } + // We have `size < min_align`. Round `size` *down* to the next power of two and use that. + fn prev_power_of_two(x: u64) -> u64 { + let next_pow2 = x.next_power_of_two(); + if next_pow2 == x { + // x *is* a power of two, just use that. + x + } else { + // x is between two powers, so next = 2*prev. + next_pow2 / 2 } } - - Ok(None) + Align::from_bytes(prev_power_of_two(size)).unwrap() } /// Emulates calling the internal __rust_* allocator functions fn emulate_allocator( &mut self, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); }; match allocator_kind { @@ -364,23 +389,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and not execute any Miri shim. Somewhat unintuitively doing so is done // by returning `NotSupported`, which triggers the `lookup_exported_symbol` // fallback case in `emulate_foreign_item`. - return Ok(EmulateByNameResult::NotSupported); + return Ok(EmulateForeignItemResult::NotSupported); } AllocatorKind::Default => { default(this)?; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } } - /// Emulates calling a foreign item using its name. - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. @@ -391,7 +415,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_external_c_fct(link_name, dest, args)? { - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } } @@ -591,7 +615,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } _ => unreachable!(), } @@ -651,7 +675,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateByNameResult::NeedsJumping); + return Ok(EmulateForeignItemResult::NeedsJumping); } _ => unreachable!(), } @@ -981,30 +1005,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty); } } - "llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => { - // Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum. - let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; - let c_in = this.read_scalar(c_in)?.to_u8()?; - let a = this.read_scalar(a)?.to_u64()?; - let b = this.read_scalar(b)?.to_u64()?; - - #[allow(clippy::arithmetic_side_effects)] - // adding two u64 and a u8 cannot wrap in a u128 - let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b); - #[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64 - let (c_out, sum) = ((wide_sum >> 64).truncate::(), wide_sum.truncate::()); - - let c_out_field = this.project_field(dest, 0)?; - this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?; - let sum_field = this.project_field(dest, 1)?; - this.write_scalar(Scalar::from_u64(sum), &sum_field)?; - } - "llvm.x86.sse2.pause" - if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => - { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.yield_active_thread(); - } + // FIXME: Move these to an `arm` submodule. "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => { let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; @@ -1032,13 +1033,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - name if name.starts_with("llvm.x86.sse.") => { - return shims::x86::sse::EvalContextExt::emulate_x86_sse_intrinsic( - this, link_name, abi, args, dest, - ); + // Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm + // `{i,u}8x16_popcnt` functions. + name if name.starts_with("llvm.ctpop.v") => { + let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (op, op_len) = this.operand_to_simd(op)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, op_len); + + for i in 0..dest_len { + let op = this.read_immediate(&this.project_index(&op, i)?)?; + // Use `to_uint` to get a zero-extended `u128`. Those + // extra zeros will not affect `count_ones`. + let res = op.to_scalar().to_uint(op.layout.size)?.count_ones(); + + this.write_scalar( + Scalar::from_uint(res, op.layout.size), + &this.project_index(&dest, i)?, + )?; + } } - name if name.starts_with("llvm.x86.sse2.") => { - return shims::x86::sse2::EvalContextExt::emulate_x86_sse2_intrinsic( + + name if name.starts_with("llvm.x86.") + && (this.tcx.sess.target.arch == "x86" + || this.tcx.sess.target.arch == "x86_64") => + { + return shims::x86::EvalContextExt::emulate_x86_intrinsic( this, link_name, abi, args, dest, ); } @@ -1047,19 +1069,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => return match this.tcx.sess.target.os.as_ref() { target_os if target_os_is_unix(target_os) => - shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), "windows" => - shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), - _ => Ok(EmulateByNameResult::NotSupported), + _ => Ok(EmulateForeignItemResult::NotSupported), }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } /// Check some basic requirements for this allocation request: diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index ef9d071044818..8c90ceba1e4aa 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -60,7 +60,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // The rest jumps to `ret` immediately. - this.emulate_intrinsic_by_name(intrinsic_name, args, dest)?; + this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?; trace!("{:?}", this.dump_place(dest)); this.go_to_block(ret); @@ -71,6 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_intrinsic_by_name( &mut self, intrinsic_name: &str, + generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { @@ -80,7 +81,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return this.emulate_atomic_intrinsic(name, args, dest); } if let Some(name) = intrinsic_name.strip_prefix("simd_") { - return this.emulate_simd_intrinsic(name, args, dest); + return this.emulate_simd_intrinsic(name, generic_args, args, dest); } match intrinsic_name { @@ -89,10 +90,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right] = check_arg_count(args)?; let left = this.read_immediate(left)?; let right = this.read_immediate(right)?; - let (val, _overflowed, _ty) = - this.overflowing_binary_op(mir::BinOp::Eq, &left, &right)?; + let val = this.wrapping_binary_op(mir::BinOp::Eq, &left, &right)?; // We're type punning a bool as an u8 here. - this.write_scalar(val, dest)?; + this.write_scalar(val.to_scalar(), dest)?; } "const_allocate" => { // For now, for compatibility with the run-time implementation of this, we just return null. @@ -325,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "fmaf32" => { let [a, b, c] = check_arg_count(args)?; - // FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468. + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 let a = f32::from_bits(this.read_scalar(a)?.to_u32()?); let b = f32::from_bits(this.read_scalar(b)?.to_u32()?); let c = f32::from_bits(this.read_scalar(c)?.to_u32()?); @@ -335,7 +335,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "fmaf64" => { let [a, b, c] = check_arg_count(args)?; - // FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468. + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 let a = f64::from_bits(this.read_scalar(a)?.to_u64()?); let b = f64::from_bits(this.read_scalar(b)?.to_u64()?); let c = f64::from_bits(this.read_scalar(c)?.to_u64()?); @@ -369,7 +369,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ty::Float(FloatTy::F32) => { let f = val.to_scalar().to_f32()?; this - .float_to_int_checked(f, dest.layout.ty, Round::TowardZero) + .float_to_int_checked(f, dest.layout, Round::TowardZero) .ok_or_else(|| { err_ub_format!( "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", @@ -380,7 +380,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ty::Float(FloatTy::F64) => { let f = val.to_scalar().to_f64()?; this - .float_to_int_checked(f, dest.layout.ty, Round::TowardZero) + .float_to_int_checked(f, dest.layout, Round::TowardZero) .ok_or_else(|| { err_ub_format!( "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", @@ -396,7 +396,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ), }; - this.write_scalar(res, dest)?; + this.write_immediate(*res, dest)?; } // Other diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 626ead378e7be..70f90aac2c23f 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -12,6 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_simd_intrinsic( &mut self, intrinsic_name: &str, + generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { @@ -31,28 +32,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, op_len); - #[derive(Copy, Clone)] - enum HostFloatOp { - Ceil, - Floor, - Round, - Trunc, - Sqrt, - } #[derive(Copy, Clone)] enum Op { MirOp(mir::UnOp), Abs, - HostOp(HostFloatOp), + Sqrt, + Round(rustc_apfloat::Round), } let which = match intrinsic_name { "neg" => Op::MirOp(mir::UnOp::Neg), "fabs" => Op::Abs, - "ceil" => Op::HostOp(HostFloatOp::Ceil), - "floor" => Op::HostOp(HostFloatOp::Floor), - "round" => Op::HostOp(HostFloatOp::Round), - "trunc" => Op::HostOp(HostFloatOp::Trunc), - "fsqrt" => Op::HostOp(HostFloatOp::Sqrt), + "fsqrt" => Op::Sqrt, + "ceil" => Op::Round(rustc_apfloat::Round::TowardPositive), + "floor" => Op::Round(rustc_apfloat::Round::TowardNegative), + "round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway), + "trunc" => Op::Round(rustc_apfloat::Round::TowardZero), _ => unreachable!(), }; @@ -60,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = this.read_immediate(&this.project_index(&op, i)?)?; let dest = this.project_index(&dest, i)?; let val = match which { - Op::MirOp(mir_op) => this.unary_op(mir_op, &op)?.to_scalar(), + Op::MirOp(mir_op) => this.wrapping_unary_op(mir_op, &op)?.to_scalar(), Op::Abs => { // Works for f32 and f64. let ty::Float(float_ty) = op.layout.ty.kind() else { @@ -72,7 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()), } } - Op::HostOp(host_op) => { + Op::Sqrt => { let ty::Float(float_ty) = op.layout.ty.kind() else { span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) }; @@ -80,28 +74,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match float_ty { FloatTy::F32 => { let f = f32::from_bits(op.to_scalar().to_u32()?); - let res = match host_op { - HostFloatOp::Ceil => f.ceil(), - HostFloatOp::Floor => f.floor(), - HostFloatOp::Round => f.round(), - HostFloatOp::Trunc => f.trunc(), - HostFloatOp::Sqrt => f.sqrt(), - }; + let res = f.sqrt(); Scalar::from_u32(res.to_bits()) } FloatTy::F64 => { let f = f64::from_bits(op.to_scalar().to_u64()?); - let res = match host_op { - HostFloatOp::Ceil => f.ceil(), - HostFloatOp::Floor => f.floor(), - HostFloatOp::Round => f.round(), - HostFloatOp::Trunc => f.trunc(), - HostFloatOp::Sqrt => f.sqrt(), - }; + let res = f.sqrt(); Scalar::from_u64(res.to_bits()) } } - + } + Op::Round(rounding) => { + let ty::Float(float_ty) = op.layout.ty.kind() else { + span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) + }; + match float_ty { + FloatTy::F32 => { + let f = op.to_scalar().to_f32()?; + let res = f.round_to_integral(rounding).value; + Scalar::from_f32(res) + } + FloatTy::F64 => { + let f = op.to_scalar().to_f64()?; + let res = f.round_to_integral(rounding).value; + Scalar::from_f64(res) + } + } } }; this.write_scalar(val, &dest)?; @@ -177,7 +175,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; let val = match which { Op::MirOp(mir_op) => { - let (val, overflowed, ty) = this.overflowing_binary_op(mir_op, &left, &right)?; + let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?; if matches!(mir_op, BinOp::Shl | BinOp::Shr) { // Shifts have extra UB as SIMD operations that the MIR binop does not have. // See . @@ -188,13 +186,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) { // Special handling for boolean-returning operations - assert_eq!(ty, this.tcx.types.bool); - let val = val.to_bool().unwrap(); + assert_eq!(val.layout.ty, this.tcx.types.bool); + let val = val.to_scalar().to_bool().unwrap(); bool_to_simd_element(val, dest.layout.size) } else { - assert_ne!(ty, this.tcx.types.bool); - assert_eq!(ty, dest.layout.ty); - val + assert_ne!(val.layout.ty, this.tcx.types.bool); + assert_eq!(val.layout.ty, dest.layout.ty); + val.to_scalar() } } Op::SaturatingOp(mir_op) => { @@ -304,18 +302,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = this.read_immediate(&this.project_index(&op, i)?)?; res = match which { Op::MirOp(mir_op) => { - this.binary_op(mir_op, &res, &op)? + this.wrapping_binary_op(mir_op, &res, &op)? } Op::MirOpBool(mir_op) => { let op = imm_from_bool(simd_element_to_bool(op)?); - this.binary_op(mir_op, &res, &op)? + this.wrapping_binary_op(mir_op, &res, &op)? } Op::Max => { if matches!(res.layout.ty.kind(), ty::Float(_)) { ImmTy::from_scalar(fmax_op(&res, &op)?, res.layout) } else { // Just boring integers, so NaNs to worry about - if this.binary_op(BinOp::Ge, &res, &op)?.to_scalar().to_bool()? { + if this.wrapping_binary_op(BinOp::Ge, &res, &op)?.to_scalar().to_bool()? { res } else { op @@ -327,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ImmTy::from_scalar(fmin_op(&res, &op)?, res.layout) } else { // Just boring integers, so NaNs to worry about - if this.binary_op(BinOp::Le, &res, &op)?.to_scalar().to_bool()? { + if this.wrapping_binary_op(BinOp::Le, &res, &op)?.to_scalar().to_bool()? { res } else { op @@ -356,7 +354,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut res = init; for i in 0..op_len { let op = this.read_immediate(&this.project_index(&op, i)?)?; - res = this.binary_op(mir_op, &res, &op)?; + res = this.wrapping_binary_op(mir_op, &res, &op)?; } this.write_immediate(*res, dest)?; } @@ -441,44 +439,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Int-to-(int|float): always safe (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast => - this.int_to_int_or_float(&op, dest.layout.ty)?, + this.int_to_int_or_float(&op, dest.layout)?, // Float-to-float: always safe (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast => - this.float_to_float_or_int(&op, dest.layout.ty)?, + this.float_to_float_or_int(&op, dest.layout)?, // Float-to-int in safe mode (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => - this.float_to_float_or_int(&op, dest.layout.ty)?, + this.float_to_float_or_int(&op, dest.layout)?, // Float-to-int in unchecked mode (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { let f = op.to_scalar().to_f32()?; - this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero) + this.float_to_int_checked(f, dest.layout, Round::TowardZero) .ok_or_else(|| { err_ub_format!( "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", dest.layout.ty ) })? - .into() } (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { let f = op.to_scalar().to_f64()?; - this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero) + this.float_to_int_checked(f, dest.layout, Round::TowardZero) .ok_or_else(|| { err_ub_format!( "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", dest.layout.ty ) })? - .into() } // Ptr-to-ptr cast (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => - this.ptr_to_ptr(&op, dest.layout.ty)?, + this.ptr_to_ptr(&op, dest.layout)?, // Ptr/Int casts (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => - this.pointer_expose_address_cast(&op, dest.layout.ty)?, + this.pointer_expose_address_cast(&op, dest.layout)?, (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => - this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?, + this.pointer_from_exposed_address_cast(&op, dest.layout)?, // Error otherwise _ => throw_unsup_format!( @@ -487,7 +483,45 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { to_ty = dest.layout.ty, ), }; - this.write_immediate(val, &dest)?; + this.write_immediate(*val, &dest)?; + } + } + "shuffle_generic" => { + let [left, right] = check_arg_count(args)?; + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + let index = generic_args[2] + .expect_const() + .eval(*this.tcx, this.param_env(), Some(this.tcx.span)) + .unwrap() + .unwrap_branch(); + let index_len = index.len(); + + assert_eq!(left_len, right_len); + assert_eq!(index_len as u64, dest_len); + + for i in 0..dest_len { + let src_index: u64 = index[usize::try_from(i).unwrap()] + .unwrap_leaf() + .try_to_u32() + .unwrap() + .into(); + let dest = this.project_index(&dest, i)?; + + let val = if src_index < left_len { + this.read_immediate(&this.project_index(&left, src_index)?)? + } else if src_index < left_len.checked_add(right_len).unwrap() { + let right_idx = src_index.checked_sub(left_len).unwrap(); + this.read_immediate(&this.project_index(&right, right_idx)?)? + } else { + span_bug!( + this.cur_span(), + "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}", + ); + }; + this.write_immediate(*val, &dest)?; } } "shuffle" => { diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 5a9574766f3d9..a031a2a25c968 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -9,7 +9,6 @@ pub mod unix; pub mod windows; mod x86; -pub mod dlsym; pub mod env; pub mod os_str; pub mod panic; @@ -58,7 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // foreign function // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind); + let link_name = this.item_link_name(instance.def_id()); + return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); } // Otherwise, load the MIR. diff --git a/src/tools/miri/src/shims/unix/android/dlsym.rs b/src/tools/miri/src/shims/unix/android/dlsym.rs deleted file mode 100644 index 451bc0bd5e153..0000000000000 --- a/src/tools/miri/src/shims/unix/android/dlsym.rs +++ /dev/null @@ -1,54 +0,0 @@ -use rustc_middle::mir; - -use crate::helpers::check_arg_count; -use crate::*; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - signal, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "signal" => Some(Dlsym::signal), - "android_set_abort_message" => None, - _ => throw_unsup_format!("unsupported Android dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "android"); - - match dlsym { - Dlsym::signal => { - if !this.frame_in_std() { - throw_unsup_format!( - "`signal` support is crude and just enough for libstd to work" - ); - } - - let [_sig, _func] = check_arg_count(args)?; - this.write_null(dest)?; - } - } - - log::trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 756aed369f15b..f61ebd5a3a8dc 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -2,25 +2,29 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub fn is_dyn_sym(_name: &str) -> bool { + false +} + pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + #[allow(unused, clippy::match_single_binding)] // there isn't anything here yet + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - _abi: Abi, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { - let _this = self.eval_context_mut(); - #[allow(clippy::match_single_binding)] + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, EmulateForeignItemResult> { + let this = self.eval_context_mut(); + match link_name.as_str() { - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - #[allow(unreachable_code)] - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/android/mod.rs +++ b/src/tools/miri/src/shims/unix/android/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/dlsym.rs b/src/tools/miri/src/shims/unix/dlsym.rs deleted file mode 100644 index 8bc19d18f2b29..0000000000000 --- a/src/tools/miri/src/shims/unix/dlsym.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use crate::*; -use shims::unix::android::dlsym as android; -use shims::unix::freebsd::dlsym as freebsd; -use shims::unix::linux::dlsym as linux; -use shims::unix::macos::dlsym as macos; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - Android(android::Dlsym), - FreeBsd(freebsd::Dlsym), - Linux(linux::Dlsym), - MacOs(macos::Dlsym), -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str, target_os: &str) -> InterpResult<'tcx, Option> { - Ok(match target_os { - "android" => android::Dlsym::from_str(name)?.map(Dlsym::Android), - "freebsd" => freebsd::Dlsym::from_str(name)?.map(Dlsym::FreeBsd), - "linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux), - "macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs), - _ => panic!("unsupported Unix OS {target_os}"), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - this.check_abi(abi, Abi::C { unwind: false })?; - - match dlsym { - Dlsym::Android(dlsym) => - android::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::FreeBsd(dlsym) => - freebsd::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, dest, ret), - } - } -} diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 4bcca5076cac2..c013d27502927 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1,4 +1,5 @@ use std::ffi::OsStr; +use std::str; use log::trace; @@ -8,24 +9,48 @@ use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +use shims::unix::android::foreign_items as android; +use shims::unix::freebsd::foreign_items as freebsd; +use shims::unix::linux::foreign_items as linux; +use shims::unix::macos::foreign_items as macos; + +fn is_dyn_sym(name: &str, target_os: &str) -> bool { + match name { + // Used for tests. + "isatty" => true, + // `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as + // well allow it in `dlsym`. + "signal" => true, + // Give specific OSes a chance to allow their symbols. + _ => + match target_os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + target_os => panic!("unsupported Unix OS {target_os}"), + }, + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. #[rustfmt::skip] match link_name.as_str() { // Environment related shims @@ -230,9 +255,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; - let symbol_name = this.read_c_str(symbol)?; - if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + let name = this.read_c_str(symbol)?; + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name, &this.tcx.sess.target.os) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; @@ -565,7 +590,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "getuid" if this.frame_in_std() => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FOr now, just pretend we always have this fixed UID. + // For now, just pretend we always have this fixed UID. this.write_int(super::UID, dest)?; } @@ -609,15 +634,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "freebsd" => shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "linux" => shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "macos" => shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - _ => Ok(EmulateByNameResult::NotSupported), + "android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), + _ => Ok(EmulateForeignItemResult::NotSupported), }; } }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs b/src/tools/miri/src/shims/unix/freebsd/dlsym.rs deleted file mode 100644 index d759ffb8994b7..0000000000000 --- a/src/tools/miri/src/shims/unix/freebsd/dlsym.rs +++ /dev/null @@ -1,36 +0,0 @@ -use rustc_middle::mir; - -use crate::*; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym {} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - throw_unsup_format!("unsupported FreeBSD dlsym: {}", name) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let _ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "freebsd"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index d755e5f10bae8..869434e8876ed 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -2,19 +2,22 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::thread::EvalContextExt as _; -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub fn is_dyn_sym(_name: &str) -> bool { + false +} +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading @@ -42,8 +45,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/mod.rs b/src/tools/miri/src/shims/unix/freebsd/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/freebsd/mod.rs +++ b/src/tools/miri/src/shims/unix/freebsd/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 8963dfb97a6e5..1014a61b75ed2 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -63,7 +63,7 @@ pub trait FileDescriptor: std::fmt::Debug + Any { fn dup(&mut self) -> io::Result>; - fn is_tty(&self) -> bool { + fn is_tty(&self, _communicate_allowed: bool) -> bool { false } @@ -156,8 +156,8 @@ impl FileDescriptor for FileHandle { Some(self.file.as_raw_fd()) } - fn is_tty(&self) -> bool { - self.file.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.file.is_terminal() } } @@ -188,8 +188,8 @@ impl FileDescriptor for io::Stdin { Some(libc::STDIN_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -225,8 +225,8 @@ impl FileDescriptor for io::Stdout { Some(libc::STDOUT_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -255,8 +255,8 @@ impl FileDescriptor for io::Stderr { Some(libc::STDERR_FILENO) } - fn is_tty(&self) -> bool { - self.is_terminal() + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() } } @@ -1721,15 +1721,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); // "returns 1 if fd is an open file descriptor referring to a terminal; // otherwise 0 is returned, and errno is set to indicate the error" - if matches!(this.machine.isolated_op, IsolatedOp::Allow) { - let fd = this.read_scalar(miri_fd)?.to_i32()?; - if this.machine.file_handler.handles.get(&fd).map(|fd| fd.is_tty()) == Some(true) { + let fd = this.read_scalar(miri_fd)?.to_i32()?; + let error = if let Some(fd) = this.machine.file_handler.handles.get(&fd) { + if fd.is_tty(this.machine.communicate()) { return Ok(Scalar::from_i32(1)); + } else { + this.eval_libc("ENOTTY") } - } - // Fallback when the FD was not found or isolation is enabled. - let enotty = this.eval_libc("ENOTTY"); - this.set_last_error(enotty)?; + } else { + // FD does not exist + this.eval_libc("EBADF") + }; + this.set_last_error(error)?; Ok(Scalar::from_i32(0)) } diff --git a/src/tools/miri/src/shims/unix/linux/dlsym.rs b/src/tools/miri/src/shims/unix/linux/dlsym.rs deleted file mode 100644 index a96c14c142b25..0000000000000 --- a/src/tools/miri/src/shims/unix/linux/dlsym.rs +++ /dev/null @@ -1,40 +0,0 @@ -use rustc_middle::mir; - -use crate::*; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym {} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "__pthread_get_minstack" => None, - "getrandom" => None, // std falls back to syscall(SYS_getrandom, ...) when this is NULL. - "statx" => None, // std falls back to syscall(SYS_statx, ...) when this is NULL. - _ => throw_unsup_format!("unsupported Linux dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - _args: &[OpTy<'tcx, Provenance>], - _dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let _ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "linux"); - - match dlsym {} - - //trace!("{:?}", this.dump_place(**dest)); - //this.go_to_block(ret); - //Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 1bd751c59811f..6937e0f089ec8 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -4,7 +4,7 @@ use rustc_target::spec::abi::Abi; use crate::machine::SIGRTMAX; use crate::machine::SIGRTMIN; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::linux::fd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; @@ -12,18 +12,22 @@ use shims::unix::linux::sync::futex; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "getrandom") +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno @@ -182,7 +186,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } id => { this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; - return Ok(EmulateByNameResult::AlreadyJumped); + return Ok(EmulateForeignItemResult::AlreadyJumped); } } } @@ -213,10 +217,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs index 856ec226de8fc..fe18f1a32fd42 100644 --- a/src/tools/miri/src/shims/unix/linux/mod.rs +++ b/src/tools/miri/src/shims/unix/linux/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod fd; pub mod foreign_items; pub mod mem; diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs deleted file mode 100644 index 63ad680de60fa..0000000000000 --- a/src/tools/miri/src/shims/unix/macos/dlsym.rs +++ /dev/null @@ -1,52 +0,0 @@ -use rustc_middle::mir; - -use log::trace; - -use crate::*; -use helpers::check_arg_count; - -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum Dlsym { - getentropy, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "getentropy" => Some(Dlsym::getentropy), - _ => throw_unsup_format!("unsupported macOS dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "macos"); - - match dlsym { - Dlsym::getentropy => { - let [ptr, len] = check_arg_count(args)?; - let ptr = this.read_pointer(ptr)?; - let len = this.read_target_usize(len)?; - this.gen_random(ptr, len)?; - this.write_null(dest)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 0ee3cea05d508..5881a3f46f295 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -2,22 +2,26 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; +pub fn is_dyn_sym(name: &str) -> bool { + matches!(name, "getentropy") +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. match link_name.as_str() { // errno @@ -109,6 +113,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } + // Random generation related shims + "getentropy" => { + let [buf, bufsize] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let buf = this.read_pointer(buf)?; + let bufsize = this.read_target_usize(bufsize)?; + + this.gen_random(buf, bufsize)?; + + this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS + } + // Access to command-line arguments "_NSGetArgc" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -193,9 +209,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), }; - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/macos/mod.rs b/src/tools/miri/src/shims/unix/macos/mod.rs index 434f5f30b5a56..09c6507b24f84 100644 --- a/src/tools/miri/src/shims/unix/macos/mod.rs +++ b/src/tools/miri/src/shims/unix/macos/mod.rs @@ -1,2 +1 @@ -pub mod dlsym; pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index a8ebd369abaaa..2f8014933521f 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod fs; diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs deleted file mode 100644 index e5afee35905d0..0000000000000 --- a/src/tools/miri/src/shims/windows/dlsym.rs +++ /dev/null @@ -1,82 +0,0 @@ -use rustc_middle::mir; -use rustc_target::spec::abi::Abi; - -use log::trace; - -use crate::helpers::check_arg_count; -use crate::shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; -use crate::shims::windows::sync::EvalContextExt as _; -use crate::*; - -#[derive(Debug, Copy, Clone)] -pub enum Dlsym { - SetThreadDescription, - WaitOnAddress, - WakeByAddressSingle, -} - -impl Dlsym { - // Returns an error for unsupported symbols, and None if this symbol - // should become a NULL pointer (pretend it does not exist). - pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option> { - Ok(match name { - "GetSystemTimePreciseAsFileTime" => None, - "SetThreadDescription" => Some(Dlsym::SetThreadDescription), - "WaitOnAddress" => Some(Dlsym::WaitOnAddress), - "WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle), - _ => throw_unsup_format!("unsupported Windows dlsym: {}", name), - }) - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn call_dlsym( - &mut self, - dlsym: Dlsym, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let ret = ret.expect("we don't support any diverging dlsym"); - assert!(this.tcx.sess.target.os == "windows"); - - this.check_abi(abi, Abi::System { unwind: false })?; - - match dlsym { - Dlsym::SetThreadDescription => { - let [handle, name] = check_arg_count(args)?; - - let handle = this.read_scalar(handle)?; - - let name = this.read_wide_str(this.read_pointer(name)?)?; - - let thread = match Handle::from_scalar(handle, this)? { - Some(Handle::Thread(thread)) => thread, - Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), - _ => this.invalid_handle("SetThreadDescription")?, - }; - - this.set_thread_name_wide(thread, &name); - - this.write_null(dest)?; - } - Dlsym::WaitOnAddress => { - let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?; - - this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; - } - Dlsym::WakeByAddressSingle => { - let [ptr_op] = check_arg_count(args)?; - - this.WakeByAddressSingle(ptr_op)?; - } - } - - trace!("{:?}", this.dump_place(dest)); - this.go_to_block(ret); - Ok(()) - } -} diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index d76d01b07891a..759a412c16a25 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1,27 +1,32 @@ use std::iter; +use std::str; use rustc_span::Symbol; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; use shims::windows::sync::EvalContextExt as _; use shims::windows::thread::EvalContextExt as _; +fn is_dyn_sym(name: &str) -> bool { + matches!(name, "SetThreadDescription" | "WaitOnAddress" | "WakeByAddressSingle") +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn emulate_foreign_item_by_name( + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); - // See `fn emulate_foreign_item_by_name` in `shims/foreign_items.rs` for the general pattern. + // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. // Windows API stubs. // HANDLE = isize @@ -326,6 +331,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.WakeAllConditionVariable(condvar)?; } + "WaitOnAddress" => { + let [ptr_op, compare_op, size_op, timeout_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; + } + "WakeByAddressSingle" => { + let [ptr_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeByAddressSingle(ptr_op)?; + } // Dynamic symbol loading "GetProcAddress" => { @@ -334,14 +351,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; - if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? { - let ptr = this.fn_ptr(FnVal::Other(dlsym)); + if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; } } + // Threading + "CreateThread" => { + let [security, stacksize, start, arg, flags, thread] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let thread_id = + this.CreateThread(security, stacksize, start, arg, flags, thread)?; + + this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; + } + "WaitForSingleObject" => { + let [handle, timeout] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let ret = this.WaitForSingleObject(handle, timeout)?; + this.write_scalar(Scalar::from_u32(ret), dest)?; + } + "GetCurrentThread" => { + let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.write_scalar( + Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), + dest, + )?; + } + "SetThreadDescription" => { + let [handle, name] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + let handle = this.read_scalar(handle)?; + + let name = this.read_wide_str(this.read_pointer(name)?)?; + + let thread = match Handle::from_scalar(handle, this)? { + Some(Handle::Thread(thread)) => thread, + Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(), + _ => this.invalid_handle("SetThreadDescription")?, + }; + + this.set_thread_name_wide(thread, &name); + + this.write_null(dest)?; + } + // Miscellaneous "SystemFunction036" => { // This is really 'RtlGenRandom'. @@ -456,32 +517,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - // Threading - "CreateThread" => { - let [security, stacksize, start, arg, flags, thread] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let thread_id = - this.CreateThread(security, stacksize, start, arg, flags, thread)?; - - this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; - } - "WaitForSingleObject" => { - let [handle, timeout] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - let ret = this.WaitForSingleObject(handle, timeout)?; - this.write_scalar(Scalar::from_u32(ret), dest)?; - } - "GetCurrentThread" => { - let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - - this.write_scalar( - Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), - dest, - )?; - } - // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "GetProcessHeap" if this.frame_in_std() => { @@ -548,9 +583,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/windows/mod.rs b/src/tools/miri/src/shims/windows/mod.rs index 40fe71b2dbd02..7688abe412b99 100644 --- a/src/tools/miri/src/shims/windows/mod.rs +++ b/src/tools/miri/src/shims/windows/mod.rs @@ -1,4 +1,3 @@ -pub mod dlsym; pub mod foreign_items; mod handle; diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index ccc729aae1a2e..53a4a1ef28a7f 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -1,11 +1,110 @@ use rustc_middle::mir; +use rustc_span::Symbol; use rustc_target::abi::Size; +use rustc_target::spec::abi::Abi; use crate::*; use helpers::bool_to_simd_element; +use shims::foreign_items::EmulateForeignItemResult; -pub(super) mod sse; -pub(super) mod sse2; +mod sse; +mod sse2; +mod sse3; +mod ssse3; + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: + crate::MiriInterpCxExt<'mir, 'tcx> +{ + fn emulate_x86_intrinsic( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, EmulateForeignItemResult> { + let this = self.eval_context_mut(); + // Prefix should have already been checked. + let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap(); + match unprefixed_name { + // Used to implement the `_addcarry_u32` and `_addcarry_u64` functions. + // Computes a + b with input and output carry. The input carry is an 8-bit + // value, which is interpreted as 1 if it is non-zero. The output carry is + // an 8-bit value that will be 0 or 1. + // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html + "addcarry.32" | "addcarry.64" => { + if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" { + return Ok(EmulateForeignItemResult::NotSupported); + } + + let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; + let c_in = this.read_scalar(c_in)?.to_u8()? != 0; + let a = this.read_immediate(a)?; + let b = this.read_immediate(b)?; + + let (sum, overflow1) = this.overflowing_binary_op(mir::BinOp::Add, &a, &b)?; + let (sum, overflow2) = this.overflowing_binary_op( + mir::BinOp::Add, + &sum, + &ImmTy::from_uint(c_in, a.layout), + )?; + let c_out = overflow1 | overflow2; + + this.write_scalar(Scalar::from_u8(c_out.into()), &this.project_field(dest, 0)?)?; + this.write_immediate(*sum, &this.project_field(dest, 1)?)?; + } + // Used to implement the `_subborrow_u32` and `_subborrow_u64` functions. + // Computes a - b with input and output borrow. The input borrow is an 8-bit + // value, which is interpreted as 1 if it is non-zero. The output borrow is + // an 8-bit value that will be 0 or 1. + // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html + "subborrow.32" | "subborrow.64" => { + if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" { + return Ok(EmulateForeignItemResult::NotSupported); + } + + let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; + let b_in = this.read_scalar(b_in)?.to_u8()? != 0; + let a = this.read_immediate(a)?; + let b = this.read_immediate(b)?; + + let (sub, overflow1) = this.overflowing_binary_op(mir::BinOp::Sub, &a, &b)?; + let (sub, overflow2) = this.overflowing_binary_op( + mir::BinOp::Sub, + &sub, + &ImmTy::from_uint(b_in, a.layout), + )?; + let b_out = overflow1 | overflow2; + + this.write_scalar(Scalar::from_u8(b_out.into()), &this.project_field(dest, 0)?)?; + this.write_immediate(*sub, &this.project_field(dest, 1)?)?; + } + + name if name.starts_with("sse.") => { + return sse::EvalContextExt::emulate_x86_sse_intrinsic( + this, link_name, abi, args, dest, + ); + } + name if name.starts_with("sse2.") => { + return sse2::EvalContextExt::emulate_x86_sse2_intrinsic( + this, link_name, abi, args, dest, + ); + } + name if name.starts_with("sse3.") => { + return sse3::EvalContextExt::emulate_x86_sse3_intrinsic( + this, link_name, abi, args, dest, + ); + } + name if name.starts_with("ssse3.") => { + return ssse3::EvalContextExt::emulate_x86_ssse3_intrinsic( + this, link_name, abi, args, dest, + ); + } + _ => return Ok(EmulateForeignItemResult::NotSupported), + } + Ok(EmulateForeignItemResult::NeedsJumping) + } +} /// Floating point comparison operation /// @@ -80,8 +179,8 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>( ) -> InterpResult<'tcx, Scalar> { match which { FloatBinOp::Arith(which) => { - let (res, _overflow, _ty) = this.overflowing_binary_op(which, left, right)?; - Ok(res) + let res = this.wrapping_binary_op(which, left, right)?; + Ok(res.to_scalar()) } FloatBinOp::Cmp(which) => { let left = left.to_scalar().to_float::()?; @@ -199,3 +298,44 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( Ok(()) } + +/// Horizontaly performs `which` operation on adjacent values of +/// `left` and `right` SIMD vectors and stores the result in `dest`. +fn horizontal_bin_op<'tcx>( + this: &mut crate::MiriInterpCx<'_, 'tcx>, + which: mir::BinOp, + saturating: bool, + left: &OpTy<'tcx, Provenance>, + right: &OpTy<'tcx, Provenance>, + dest: &PlaceTy<'tcx, Provenance>, +) -> InterpResult<'tcx, ()> { + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + assert_eq!(dest_len % 2, 0); + + let middle = dest_len / 2; + for i in 0..dest_len { + // `i` is the index in `dest` + // `j` is the index of the 2-item chunk in `src` + let (j, src) = + if i < middle { (i, &left) } else { (i.checked_sub(middle).unwrap(), &right) }; + // `base_i` is the index of the first item of the 2-item chunk in `src` + let base_i = j.checked_mul(2).unwrap(); + let lhs = this.read_immediate(&this.project_index(src, base_i)?)?; + let rhs = this.read_immediate(&this.project_index(src, base_i.checked_add(1).unwrap())?)?; + + let res = if saturating { + Immediate::from(this.saturating_arith(which, &lhs, &rhs)?) + } else { + *this.wrapping_binary_op(which, &lhs, &rhs)? + }; + + this.write_immediate(res, &this.project_index(&dest, i)?)?; + } + + Ok(()) +} diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 30ad088206a1e..6f0b76059f10d 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -7,17 +7,19 @@ use rand::Rng as _; use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { +pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: + crate::MiriInterpCxExt<'mir, 'tcx> +{ fn emulate_x86_sse_intrinsic( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse.").unwrap(); @@ -139,10 +141,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let left = this.read_scalar(&this.project_index(&left, 0)?)?.to_f32()?; let right = this.read_scalar(&this.project_index(&right, 0)?)?.to_f32()?; - // The difference between the com* and *ucom variants is signaling + // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, - // for that matter), so we treat equally both variants. + // for that matter), so we treat both variants equally. let res = match unprefixed_name { "comieq.ss" | "ucomieq.ss" => left == right, "comilt.ss" | "ucomilt.ss" => left < right, @@ -173,12 +175,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. - Scalar::from_int(dest.layout.size.signed_int_min(), dest.layout.size) + ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); - this.write_scalar(res, dest)?; + this.write_immediate(*res, dest)?; } // Used to implement the _mm_cvtsi32_ss and _mm_cvtsi64_ss functions. // Converts `right` from i32/i64 to f32. Returns a SIMD vector with @@ -196,8 +198,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let right = this.read_immediate(right)?; let dest0 = this.project_index(&dest, 0)?; - let res0 = this.int_to_int_or_float(&right, dest0.layout.ty)?; - this.write_immediate(res0, &dest0)?; + let res0 = this.int_to_int_or_float(&right, dest0.layout)?; + this.write_immediate(*res0, &dest0)?; for i in 1..dest_len { this.copy_op( @@ -226,9 +228,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_u32(res), dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index b68690a835c2f..c6a847b5cf824 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -10,17 +10,19 @@ use rustc_target::spec::abi::Abi; use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; use crate::*; -use shims::foreign_items::EmulateByNameResult; +use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { +pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: + crate::MiriInterpCxExt<'mir, 'tcx> +{ fn emulate_x86_sse2_intrinsic( &mut self, link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { + ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse2.").unwrap(); @@ -56,36 +58,64 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; // Widen the operands to avoid overflow - let twice_wide_ty = this.get_twice_wide_int_ty(left.layout.ty); - let twice_wide_layout = this.layout_of(twice_wide_ty)?; - let left = this.int_to_int_or_float(&left, twice_wide_ty)?; - let right = this.int_to_int_or_float(&right, twice_wide_ty)?; + let twice_wide = this.layout_of(this.get_twice_wide_int_ty(left.layout.ty))?; + let left = this.int_to_int_or_float(&left, twice_wide)?; + let right = this.int_to_int_or_float(&right, twice_wide)?; // Calculate left + right + 1 - let (added, _overflow, _ty) = this.overflowing_binary_op( + let added = this.wrapping_binary_op(mir::BinOp::Add, &left, &right)?; + let added = this.wrapping_binary_op( mir::BinOp::Add, - &ImmTy::from_immediate(left, twice_wide_layout), - &ImmTy::from_immediate(right, twice_wide_layout), - )?; - let (added, _overflow, _ty) = this.overflowing_binary_op( - mir::BinOp::Add, - &ImmTy::from_scalar(added, twice_wide_layout), - &ImmTy::from_uint(1u32, twice_wide_layout), + &added, + &ImmTy::from_uint(1u32, twice_wide), )?; // Calculate (left + right + 1) / 2 - let (divided, _overflow, _ty) = this.overflowing_binary_op( + let divided = this.wrapping_binary_op( mir::BinOp::Div, - &ImmTy::from_scalar(added, twice_wide_layout), - &ImmTy::from_uint(2u32, twice_wide_layout), + &added, + &ImmTy::from_uint(2u32, twice_wide), )?; // Narrow back to the original type - let res = this.int_to_int_or_float( - &ImmTy::from_scalar(divided, twice_wide_layout), - dest.layout.ty, - )?; - this.write_immediate(res, &dest)?; + let res = this.int_to_int_or_float(÷d, dest.layout)?; + this.write_immediate(*res, &dest)?; + } + } + // Used to implement the _mm_madd_epi16 function. + // Multiplies packed signed 16-bit integers in `left` and `right`, producing + // intermediate signed 32-bit integers. Horizontally add adjacent pairs of + // intermediate 32-bit integers, and pack the results in `dest`. + "pmadd.wd" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(left_len, right_len); + assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); + + for i in 0..dest_len { + let j1 = i.checked_mul(2).unwrap(); + let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?; + let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?; + + let j2 = j1.checked_add(1).unwrap(); + let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?; + let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?; + + let dest = this.project_index(&dest, i)?; + + // Multiplications are i16*i16->i32, which will not overflow. + let mul1 = i32::from(left1).checked_mul(right1.into()).unwrap(); + let mul2 = i32::from(left2).checked_mul(right2.into()).unwrap(); + // However, this addition can overflow in the most extreme case + // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000 + let res = mul1.wrapping_add(mul2); + + this.write_scalar(Scalar::from_i32(res), &dest)?; } } // Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions. @@ -106,30 +136,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; // Widen the operands to avoid overflow - let twice_wide_ty = this.get_twice_wide_int_ty(left.layout.ty); - let twice_wide_layout = this.layout_of(twice_wide_ty)?; - let left = this.int_to_int_or_float(&left, twice_wide_ty)?; - let right = this.int_to_int_or_float(&right, twice_wide_ty)?; + let twice_wide = this.layout_of(this.get_twice_wide_int_ty(left.layout.ty))?; + let left = this.int_to_int_or_float(&left, twice_wide)?; + let right = this.int_to_int_or_float(&right, twice_wide)?; // Multiply - let (multiplied, _overflow, _ty) = this.overflowing_binary_op( - mir::BinOp::Mul, - &ImmTy::from_immediate(left, twice_wide_layout), - &ImmTy::from_immediate(right, twice_wide_layout), - )?; + let multiplied = this.wrapping_binary_op(mir::BinOp::Mul, &left, &right)?; // Keep the high half - let (high, _overflow, _ty) = this.overflowing_binary_op( + let high = this.wrapping_binary_op( mir::BinOp::Shr, - &ImmTy::from_scalar(multiplied, twice_wide_layout), - &ImmTy::from_uint(dest.layout.size.bits(), twice_wide_layout), + &multiplied, + &ImmTy::from_uint(dest.layout.size.bits(), twice_wide), )?; // Narrow back to the original type - let res = this.int_to_int_or_float( - &ImmTy::from_scalar(high, twice_wide_layout), - dest.layout.ty, - )?; - this.write_immediate(res, &dest)?; + let res = this.int_to_int_or_float(&high, dest.layout)?; + this.write_immediate(*res, &dest)?; } } // Used to implement the _mm_mul_epu32 function. @@ -392,11 +414,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; let res = - this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| { + this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { // Fallback to minimum acording to SSE2 semantics. - Scalar::from_i32(i32::MIN) + ImmTy::from_int(i32::MIN, this.machine.layouts.i32) }); - this.write_scalar(res, &dest)?; + this.write_immediate(*res, &dest)?; } } // Used to implement the _mm_packs_epi16 function. @@ -426,8 +448,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let right_res = i8::try_from(right).unwrap_or(if right < 0 { i8::MIN } else { i8::MAX }); - this.write_scalar(Scalar::from_i8(left_res.try_into().unwrap()), &left_dest)?; - this.write_scalar(Scalar::from_i8(right_res.try_into().unwrap()), &right_dest)?; + this.write_scalar(Scalar::from_i8(left_res), &left_dest)?; + this.write_scalar(Scalar::from_i8(right_res), &right_dest)?; } } // Used to implement the _mm_packus_epi16 function. @@ -487,11 +509,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let right_res = i16::try_from(right).unwrap_or(if right < 0 { i16::MIN } else { i16::MAX }); - this.write_scalar(Scalar::from_i16(left_res.try_into().unwrap()), &left_dest)?; - this.write_scalar( - Scalar::from_i16(right_res.try_into().unwrap()), - &right_dest, - )?; + this.write_scalar(Scalar::from_i16(left_res), &left_dest)?; + this.write_scalar(Scalar::from_i16(right_res), &right_dest)?; } } // Used to implement _mm_min_sd and _mm_max_sd functions. @@ -618,10 +637,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let left = this.read_scalar(&this.project_index(&left, 0)?)?.to_f64()?; let right = this.read_scalar(&this.project_index(&right, 0)?)?.to_f64()?; - // The difference between the com* and *ucom variants is signaling + // The difference between the com* and ucom* variants is signaling // of exceptions when either argument is a quiet NaN. We do not // support accessing the SSE status register from miri (or from Rust, - // for that matter), so we treat equally both variants. + // for that matter), so we treat both variants equally. let res = match unprefixed_name { "comieq.sd" | "ucomieq.sd" => left == right, "comilt.sd" | "ucomilt.sd" => left < right, @@ -648,8 +667,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = this.read_immediate(&this.project_index(&op, i)?)?; let dest = this.project_index(&dest, i)?; - let res = this.float_to_float_or_int(&op, dest.layout.ty)?; - this.write_immediate(res, &dest)?; + let res = this.float_to_float_or_int(&op, dest.layout)?; + this.write_immediate(*res, &dest)?; } // For f32 -> f64, ignore the remaining // For f64 -> f32, fill the remaining with zeros @@ -685,11 +704,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; let res = - this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| { + this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { // Fallback to minimum acording to SSE2 semantics. - Scalar::from_i32(i32::MIN) + ImmTy::from_int(i32::MIN, this.machine.layouts.i32) }); - this.write_scalar(res, &dest)?; + this.write_immediate(*res, &dest)?; } // Fill the remaining with zeros for i in op_len..dest_len { @@ -716,12 +735,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. - Scalar::from_int(dest.layout.size.signed_int_min(), dest.layout.size) + ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); - this.write_scalar(res, dest)?; + this.write_immediate(*res, dest)?; } // Used to implement the _mm_cvtsd_ss and _mm_cvtss_sd functions. // Converts the first f64/f32 from `right` to f32/f64 and copies @@ -741,8 +760,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest0 = this.project_index(&dest, 0)?; // `float_to_float_or_int` here will convert from f64 to f32 (cvtsd2ss) or // from f32 to f64 (cvtss2sd). - let res0 = this.float_to_float_or_int(&right0, dest0.layout.ty)?; - this.write_immediate(res0, &dest0)?; + let res0 = this.float_to_float_or_int(&right0, dest0.layout)?; + this.write_immediate(*res0, &dest0)?; // Copy remianing from `left` for i in 1..dest_len { @@ -772,9 +791,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_u32(res.try_into().unwrap()), dest)?; } - _ => return Ok(EmulateByNameResult::NotSupported), + // Used to implement the `_mm_pause` function. + // The intrinsic is used to hint the processor that the code is in a spin-loop. + "pause" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + this.yield_active_thread(); + } + _ => return Ok(EmulateForeignItemResult::NotSupported), } - Ok(EmulateByNameResult::NeedsJumping) + Ok(EmulateForeignItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs new file mode 100644 index 0000000000000..a41de5dbf7ee5 --- /dev/null +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -0,0 +1,90 @@ +use rustc_middle::mir; +use rustc_span::Symbol; +use rustc_target::abi::Align; +use rustc_target::spec::abi::Abi; + +use super::horizontal_bin_op; +use crate::*; +use shims::foreign_items::EmulateForeignItemResult; + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: + crate::MiriInterpCxExt<'mir, 'tcx> +{ + fn emulate_x86_sse3_intrinsic( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, EmulateForeignItemResult> { + let this = self.eval_context_mut(); + // Prefix should have already been checked. + let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); + + match unprefixed_name { + // Used to implement the _mm_addsub_ps and _mm_addsub_pd functions. + // Alternatingly add and subtract floating point (f32 or f64) from + // `left` and `right` + "addsub.ps" | "addsub.pd" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + for i in 0..dest_len { + let left = this.read_immediate(&this.project_index(&left, i)?)?; + let right = this.read_immediate(&this.project_index(&right, i)?)?; + let dest = this.project_index(&dest, i)?; + + // Even elements are subtracted and odd elements are added. + let op = if i % 2 == 0 { mir::BinOp::Sub } else { mir::BinOp::Add }; + let res = this.wrapping_binary_op(op, &left, &right)?; + + this.write_immediate(*res, &dest)?; + } + } + // Used to implement the _mm_h{add,sub}_p{s,d} functions. + // Horizontally add/subtract adjacent floating point values + // in `left` and `right`. + "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let which = match unprefixed_name { + "hadd.ps" | "hadd.pd" => mir::BinOp::Add, + "hsub.ps" | "hsub.pd" => mir::BinOp::Sub, + _ => unreachable!(), + }; + + horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?; + } + // Used to implement the _mm_lddqu_si128 function. + // Reads a 128-bit vector from an unaligned pointer. This intrinsic + // is expected to perform better than a regular unaligned read when + // the data crosses a cache line, but for Miri this is just a regular + // unaligned read. + "ldu.dq" => { + let [src_ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let src_ptr = this.read_pointer(src_ptr)?; + let dest = dest.force_mplace(this)?; + + this.mem_copy( + src_ptr, + Align::ONE, + dest.ptr(), + Align::ONE, + dest.layout.size, + /*nonoverlapping*/ true, + )?; + } + _ => return Ok(EmulateForeignItemResult::NotSupported), + } + Ok(EmulateForeignItemResult::NeedsJumping) + } +} diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs new file mode 100644 index 0000000000000..dbc2b947b3322 --- /dev/null +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -0,0 +1,199 @@ +use rustc_middle::mir; +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use super::horizontal_bin_op; +use crate::*; +use shims::foreign_items::EmulateForeignItemResult; + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: + crate::MiriInterpCxExt<'mir, 'tcx> +{ + fn emulate_x86_ssse3_intrinsic( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx, Provenance>], + dest: &PlaceTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, EmulateForeignItemResult> { + let this = self.eval_context_mut(); + // Prefix should have already been checked. + let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); + + match unprefixed_name { + // Used to implement the _mm_abs_epi{8,16,32} functions. + // Calculates the absolute value of packed 8/16/32-bit integers. + "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => { + let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (op, op_len) = this.operand_to_simd(op)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(op_len, dest_len); + + for i in 0..dest_len { + let op = this.read_scalar(&this.project_index(&op, i)?)?; + let dest = this.project_index(&dest, i)?; + + // Converting to a host "i128" works since the input is always signed. + let res = op.to_int(dest.layout.size)?.unsigned_abs(); + + this.write_scalar(Scalar::from_uint(res, dest.layout.size), &dest)?; + } + } + // Used to implement the _mm_shuffle_epi8 intrinsic. + // Shuffles bytes from `left` using `right` as pattern. + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8 + "pshuf.b.128" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + for i in 0..dest_len { + let right = this.read_scalar(&this.project_index(&right, i)?)?.to_u8()?; + let dest = this.project_index(&dest, i)?; + + let res = if right & 0x80 == 0 { + let j = right % 16; // index wraps around + this.read_scalar(&this.project_index(&left, j.into())?)? + } else { + // If the highest bit in `right` is 1, write zero. + Scalar::from_u8(0) + }; + + this.write_scalar(res, &dest)?; + } + } + // Used to implement the _mm_h{add,adds,sub}_epi{16,32} functions. + // Horizontally add / add with saturation / subtract adjacent 16/32-bit + // integer values in `left` and `right`. + "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128" + | "phsub.d.128" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (which, saturating) = match unprefixed_name { + "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false), + "phadd.sw.128" => (mir::BinOp::Add, true), + "phsub.w.128" | "phsub.d.128" => (mir::BinOp::Sub, false), + "phsub.sw.128" => (mir::BinOp::Sub, true), + _ => unreachable!(), + }; + + horizontal_bin_op(this, which, saturating, left, right, dest)?; + } + // Used to implement the _mm_maddubs_epi16 function. + // Multiplies packed 8-bit unsigned integers from `left` and packed + // signed 8-bit integers from `right` into 16-bit signed integers. Then, + // the saturating sum of the products with indices `2*i` and `2*i+1` + // produces the output at index `i`. + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16 + "pmadd.ub.sw.128" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(left_len, right_len); + assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); + + for i in 0..dest_len { + let j1 = i.checked_mul(2).unwrap(); + let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_u8()?; + let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i8()?; + + let j2 = j1.checked_add(1).unwrap(); + let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_u8()?; + let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i8()?; + + let dest = this.project_index(&dest, i)?; + + // Multiplication of a u8 and an i8 into an i16 cannot overflow. + let mul1 = i16::from(left1).checked_mul(right1.into()).unwrap(); + let mul2 = i16::from(left2).checked_mul(right2.into()).unwrap(); + let res = mul1.saturating_add(mul2); + + this.write_scalar(Scalar::from_i16(res), &dest)?; + } + } + // Used to implement the _mm_mulhrs_epi16 function. + // Multiplies packed 16-bit signed integer values, truncates the 32-bit + // product to the 18 most significant bits by right-shifting, and then + // divides the 18-bit value by 2 (rounding to nearest) by first adding + // 1 and then taking the bits `1..=16`. + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16 + "pmul.hr.sw.128" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + for i in 0..dest_len { + let left = this.read_scalar(&this.project_index(&left, i)?)?.to_i16()?; + let right = this.read_scalar(&this.project_index(&right, i)?)?.to_i16()?; + let dest = this.project_index(&dest, i)?; + + let res = (i32::from(left).checked_mul(right.into()).unwrap() >> 14) + .checked_add(1) + .unwrap() + >> 1; + + // The result of this operation can overflow a signed 16-bit integer. + // When `left` and `right` are -0x8000, the result is 0x8000. + #[allow(clippy::cast_possible_truncation)] + let res = res as i16; + + this.write_scalar(Scalar::from_i16(res), &dest)?; + } + } + // Used to implement the _mm_sign_epi{8,16,32} functions. + // Negates elements from `left` when the corresponding element in + // `right` is negative. If an element from `right` is zero, zero + // is writen to the corresponding output element. + // Basically, we multiply `left` with `right.signum()`. + "psign.b.128" | "psign.w.128" | "psign.d.128" => { + let [left, right] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + for i in 0..dest_len { + let dest = this.project_index(&dest, i)?; + let left = this.read_immediate(&this.project_index(&left, i)?)?; + let right = this + .read_scalar(&this.project_index(&right, i)?)? + .to_int(dest.layout.size)?; + + let res = this.wrapping_binary_op( + mir::BinOp::Mul, + &left, + &ImmTy::from_int(right.signum(), dest.layout), + )?; + + this.write_immediate(*res, &dest)?; + } + } + _ => return Ok(EmulateForeignItemResult::NotSupported), + } + Ok(EmulateForeignItemResult::NeedsJumping) + } +} diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 3ed564b4cbbb7..8d18d8535d8f5 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -2,12 +2,42 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -16,15 +46,24 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -45,9 +84,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -56,35 +95,38 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.139" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -92,27 +134,32 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] [[package]] name = "mio" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -122,7 +169,7 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.8", + "getrandom 0.2.10", "libc", "num_cpus", "page_size", @@ -132,25 +179,34 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "page_size" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b7663cbd190cfd818d08efa8497f6cd383076688c49a391ef7c0d03cd12b561" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" dependencies = [ "libc", "winapi", @@ -168,22 +224,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "ppv-lite86" @@ -193,18 +249,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -236,54 +292,60 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", - "winapi", + "windows-sys", ] [[package]] name = "syn" -version = "1.0.107" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -292,14 +354,13 @@ dependencies = [ [[package]] name = "tokio" -version = "1.24.2" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot", @@ -312,9 +373,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", @@ -323,9 +384,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasi" @@ -341,9 +402,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -351,9 +412,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", @@ -366,9 +427,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -376,9 +437,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", @@ -389,9 +450,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" @@ -417,9 +478,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -432,42 +502,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index d1ff33379e40a..670f5c895cbd6 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -17,7 +17,7 @@ getrandom = { version = "0.2", features = ["js"] } rand = { version = "0.8", features = ["small_rng"] } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] -page_size = "0.5" +page_size = "0.6" tokio = { version = "1.24", features = ["full"] } [workspace] diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 78dd3df01ec5a..c2dccf81377e4 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -1,10 +1,11 @@ use colored::*; use regex::bytes::Regex; use std::ffi::OsString; +use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::{env, process::Command}; use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling}; -use ui_test::{status_emitter, CommandBuilder}; +use ui_test::{status_emitter, CommandBuilder, Format, RustfixMode}; fn miri_path() -> PathBuf { PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri"))) @@ -78,31 +79,21 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> program.args.push(flag); } - let bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); - let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some(); - - let output_conflict_handling = match (bless, skip_ui_checks) { - (false, false) => OutputConflictHandling::Error("./miri test --bless".into()), - (true, false) => OutputConflictHandling::Bless, - (false, true) => OutputConflictHandling::Ignore, - (true, true) => panic!("cannot use RUSTC_BLESS and MIRI_SKIP_UI_CHECKS at the same time"), - }; - let mut config = Config { target: Some(target.to_owned()), stderr_filters: STDERR.clone(), stdout_filters: STDOUT.clone(), mode, program, - output_conflict_handling, out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"), edition: Some("2021".into()), - ..Config::rustc(path.into()) + threads: std::env::var("MIRI_TEST_THREADS") + .ok() + .map(|threads| NonZeroUsize::new(threads.parse().unwrap()).unwrap()), + ..Config::rustc(path) }; - let use_std = env::var_os("MIRI_NO_STD").is_none(); - - if with_dependencies && use_std { + if with_dependencies { config.dependencies_crate_manifest_path = Some(Path::new("test_dependencies").join("Cargo.toml")); let mut builder_args = vec!["run".into()]; @@ -120,51 +111,32 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> } fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> { - let config = test_config(target, path, mode, with_dependencies); + let mut config = test_config(target, path, mode, with_dependencies); // Handle command-line arguments. - let mut after_dashdash = false; - let mut quiet = false; - let filters = std::env::args() - .skip(1) - .filter(|arg| { - if after_dashdash { - // Just propagate everything. - return true; - } - match &**arg { - "--quiet" => { - quiet = true; - false - } - "--" => { - after_dashdash = true; - false - } - s if s.starts_with('-') => { - panic!("unknown compiletest flag `{s}`"); - } - _ => true, - } - }) - .collect::>(); + let args = ui_test::Args::test()?; + let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); + config.with_args(&args, default_bless); + if let OutputConflictHandling::Error(msg) = &mut config.output_conflict_handling { + *msg = "./miri test --bless".into(); + } + if env::var_os("MIRI_SKIP_UI_CHECKS").is_some() { + assert!(!default_bless, "cannot use RUSTC_BLESS and MIRI_SKIP_UI_CHECKS at the same time"); + config.output_conflict_handling = OutputConflictHandling::Ignore; + } eprintln!(" Compiler: {}", config.program.display()); ui_test::run_tests_generic( - config, + // Only run one test suite. In the future we can add all test suites to one `Vec` and run + // them all at once, making best use of systems with high parallelism. + vec![config], // 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.display().to_string().contains(f))) - }, + ui_test::default_file_filter, // This could be used to overwrite the `Config` on a per-test basis. - |_, _| None, + |_, _, _| {}, ( - if quiet { - Box::::default() - as Box - } else { - Box::new(status_emitter::Text) + match args.format { + Format::Terse => status_emitter::Text::quiet(), + Format::Pretty => status_emitter::Text::verbose(), }, status_emitter::Gha:: { name: format!("{mode:?} {path} ({target})"), @@ -205,8 +177,6 @@ regexes! { r" +at (.*\.rs)" => " at $1", // erase generics in backtraces "([0-9]+: .*)::<.*>" => "$1", - // erase addresses in backtraces - "([0-9]+: ) +0x[0-9a-f]+ - (.*)" => "$1$2", // erase long hexadecimals r"0x[0-9a-fA-F]+[0-9a-fA-F]{2,2}" => "$$HEX", // erase specific alignments @@ -218,7 +188,7 @@ regexes! { // Windows file paths r"\\" => "/", // erase Rust stdlib path - "[^ `]*/(rust[^/]*|checkout)/library/" => "RUSTLIB/", + "[^ \n`]*/(rust[^/]*|checkout)/library/" => "RUSTLIB/", // erase platform file paths "sys/[a-z]+/" => "sys/PLATFORM/", // erase paths into the crate registry @@ -269,11 +239,22 @@ fn main() -> Result<()> { ui(Mode::Pass, "tests/pass", &target, WithoutDependencies)?; ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies)?; ui(Mode::Panic, "tests/panic", &target, WithDependencies)?; - ui(Mode::Fail { require_patterns: true }, "tests/fail", &target, WithDependencies)?; + ui( + Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled }, + "tests/fail", + &target, + WithoutDependencies, + )?; + ui( + Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled }, + "tests/fail-dep", + &target, + WithDependencies, + )?; if cfg!(target_os = "linux") { ui(Mode::Pass, "tests/extern-so/pass", &target, WithoutDependencies)?; ui( - Mode::Fail { require_patterns: true }, + Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled }, "tests/extern-so/fail", &target, WithoutDependencies, @@ -285,11 +266,17 @@ fn main() -> Result<()> { fn run_dep_mode(target: String, mut args: impl Iterator) -> 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); + let mut config = test_config( + &target, + "", + Mode::Yolo { rustfix: RustfixMode::Disabled }, + /* with dependencies */ true, + ); config.program.args.clear(); // We want to give the user full control over flags - config.build_dependencies_and_link_them()?; + let dep_args = config.build_dependencies()?; let mut cmd = config.program.build(&config.out_dir); + cmd.args(dep_args); cmd.arg(path); diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_detached.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_detached.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_detached.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_detached.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_joined.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_joined.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_joined.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_joined.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_main.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_main.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_main.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_multiple.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_multiple.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_multiple.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_multiple.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_self.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_self.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.rs diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_join_self.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/libc_pthread_join_self.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr diff --git a/src/tools/miri/tests/fail/concurrency/unwind_top_of_stack.rs b/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/unwind_top_of_stack.rs rename to src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.rs diff --git a/src/tools/miri/tests/fail/concurrency/unwind_top_of_stack.stderr b/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr similarity index 85% rename from src/tools/miri/tests/fail/concurrency/unwind_top_of_stack.stderr rename to src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr index ceb5955922a3f..fccd3fbbc9da7 100644 --- a/src/tools/miri/tests/fail/concurrency/unwind_top_of_stack.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr @@ -1,3 +1,5 @@ +WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed. +If you have a use-case for it, please file an issue. thread '' panicked at $DIR/unwind_top_of_stack.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/tools/miri/tests/fail/shims/fs/close_stdout.rs b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/close_stdout.rs rename to src/tools/miri/tests/fail-dep/shims/fs/close_stdout.rs diff --git a/src/tools/miri/tests/fail/shims/fs/close_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/close_stdout.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_stdin.rs b/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/isolated_stdin.rs rename to src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.rs diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_stdin.stderr b/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/isolated_stdin.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr diff --git a/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.rs b/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.rs rename to src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.rs diff --git a/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr b/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr diff --git a/src/tools/miri/tests/fail/shims/fs/read_from_stdout.rs b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/read_from_stdout.rs rename to src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.rs diff --git a/src/tools/miri/tests/fail/shims/fs/read_from_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/read_from_stdout.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr diff --git a/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.rs rename to src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.rs diff --git a/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr diff --git a/src/tools/miri/tests/fail/shims/fs/write_to_stdin.rs b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/write_to_stdin.rs rename to src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.rs diff --git a/src/tools/miri/tests/fail/shims/fs/write_to_stdin.stderr b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/fs/write_to_stdin.stderr rename to src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr diff --git a/src/tools/miri/tests/fail/shims/memchr_null.rs b/src/tools/miri/tests/fail-dep/shims/memchr_null.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/memchr_null.rs rename to src/tools/miri/tests/fail-dep/shims/memchr_null.rs diff --git a/src/tools/miri/tests/fail/shims/memchr_null.stderr b/src/tools/miri/tests/fail-dep/shims/memchr_null.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/memchr_null.stderr rename to src/tools/miri/tests/fail-dep/shims/memchr_null.stderr diff --git a/src/tools/miri/tests/fail/shims/memcmp_null.rs b/src/tools/miri/tests/fail-dep/shims/memcmp_null.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/memcmp_null.rs rename to src/tools/miri/tests/fail-dep/shims/memcmp_null.rs diff --git a/src/tools/miri/tests/fail/shims/memcmp_null.stderr b/src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/memcmp_null.stderr rename to src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr diff --git a/src/tools/miri/tests/fail/shims/memcmp_zero.rs b/src/tools/miri/tests/fail-dep/shims/memcmp_zero.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/memcmp_zero.rs rename to src/tools/miri/tests/fail-dep/shims/memcmp_zero.rs diff --git a/src/tools/miri/tests/fail/shims/memcmp_zero.stderr b/src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/memcmp_zero.stderr rename to src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr diff --git a/src/tools/miri/tests/fail/shims/memcpy_zero.rs b/src/tools/miri/tests/fail-dep/shims/memcpy_zero.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/memcpy_zero.rs rename to src/tools/miri/tests/fail-dep/shims/memcpy_zero.rs diff --git a/src/tools/miri/tests/fail/shims/memcpy_zero.stderr b/src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/memcpy_zero.stderr rename to src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr diff --git a/src/tools/miri/tests/fail/shims/memrchr_null.rs b/src/tools/miri/tests/fail-dep/shims/memrchr_null.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/memrchr_null.rs rename to src/tools/miri/tests/fail-dep/shims/memrchr_null.rs diff --git a/src/tools/miri/tests/fail/shims/memrchr_null.stderr b/src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/memrchr_null.stderr rename to src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr diff --git a/src/tools/miri/tests/fail/shims/mmap_invalid_dealloc.rs b/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/mmap_invalid_dealloc.rs rename to src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.rs diff --git a/src/tools/miri/tests/fail/shims/mmap_invalid_dealloc.stderr b/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/mmap_invalid_dealloc.stderr rename to src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr diff --git a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs rename to src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.rs diff --git a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr rename to src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr diff --git a/src/tools/miri/tests/fail/shims/munmap.rs b/src/tools/miri/tests/fail-dep/shims/munmap.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/munmap.rs rename to src/tools/miri/tests/fail-dep/shims/munmap.rs diff --git a/src/tools/miri/tests/fail/shims/munmap.stderr b/src/tools/miri/tests/fail-dep/shims/munmap.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/munmap.stderr rename to src/tools/miri/tests/fail-dep/shims/munmap.stderr diff --git a/src/tools/miri/tests/fail/shims/munmap_partial.rs b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/munmap_partial.rs rename to src/tools/miri/tests/fail-dep/shims/munmap_partial.rs diff --git a/src/tools/miri/tests/fail/shims/munmap_partial.stderr b/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/munmap_partial.stderr rename to src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_cond_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_cond_double_destroy.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_cond_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_cond_double_destroy.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_condattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_condattr_double_destroy.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_condattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_condattr_double_destroy.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_NULL_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_NULL_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_default_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_default_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_default_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_default_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_destroy_locked.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_destroy_locked.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_destroy_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_destroy_locked.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_double_destroy.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_double_destroy.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_wrong_owner.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_wrong_owner.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutex_wrong_owner.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutexattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutexattr_double_destroy.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_mutexattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_mutexattr_double_destroy.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_read_locked.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_read_locked.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_write_locked.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_write_locked.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_double_destroy.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_double_destroy.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_double_destroy.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_wrong_owner.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_wrong_owner.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_unlock_unlocked.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_unlock_unlocked.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_wrong_owner.rs b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.rs similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_wrong_owner.rs rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.rs diff --git a/src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr similarity index 100% rename from src/tools/miri/tests/fail/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr rename to src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr diff --git a/src/tools/miri/tests/fail/tokio/sleep.rs b/src/tools/miri/tests/fail-dep/tokio/sleep.rs similarity index 100% rename from src/tools/miri/tests/fail/tokio/sleep.rs rename to src/tools/miri/tests/fail-dep/tokio/sleep.rs diff --git a/src/tools/miri/tests/fail/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr similarity index 100% rename from src/tools/miri/tests/fail/tokio/sleep.stderr rename to src/tools/miri/tests/fail-dep/tokio/sleep.stderr diff --git a/src/tools/miri/tests/fail/unsupported_incomplete_function.rs b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.rs similarity index 100% rename from src/tools/miri/tests/fail/unsupported_incomplete_function.rs rename to src/tools/miri/tests/fail-dep/unsupported_incomplete_function.rs diff --git a/src/tools/miri/tests/fail/unsupported_incomplete_function.stderr b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr similarity index 100% rename from src/tools/miri/tests/fail/unsupported_incomplete_function.stderr rename to src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr index 2a9b4d688a912..3271a04eae745 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr @@ -5,18 +5,18 @@ LL | *x = 1; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut1.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &mut i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/aliasing_mut1.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &mut i32) { | ^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr index d4858975ef103..f2694b51ca40a 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr @@ -5,18 +5,18 @@ LL | *y = 2; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut2.rs:LL:CC | LL | pub fn safe(x: &i32, y: &mut i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a foreign read access at offsets [0x0..0x4] --> $DIR/aliasing_mut2.rs:LL:CC | LL | let _v = *x; | ^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr index d1afca84a8b2e..595381c16ad97 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr @@ -5,18 +5,18 @@ LL | *x = 1; | ^^^^^^ write access through is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental - = help: the accessed tag has state Frozen which forbids this child write access + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/aliasing_mut3.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &i32) { | ^ -help: the accessed tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the accessed tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/aliasing_mut3.rs:LL:CC | LL | pub fn safe(x: &mut i32, y: &i32) { | ^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr index 0cba380ea1a30..fcabb751db947 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr @@ -24,7 +24,7 @@ note: inside closure | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ -note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>` +note: inside `dealloc_while_running::<{closure@$DIR/newtype_pair_retagging.rs:LL:CC}>` --> $DIR/newtype_pair_retagging.rs:LL:CC | LL | dealloc(); diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr index f26fc6cbaae26..456af0f1eac71 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr @@ -6,7 +6,7 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag is foreign to the protected tag (i.e., it is not a child) - = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Frozen) to become Disabled + = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Reserved (conflicted)) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/newtype_pair_retagging.rs:LL:CC @@ -18,12 +18,12 @@ help: the protected tag was created here, in the initial state Reserved | LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { | ^^ -help: the protected tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the protected tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/newtype_pair_retagging.rs:LL:CC | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC @@ -35,7 +35,7 @@ note: inside closure | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^^^^^^^ -note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>` +note: inside `dealloc_while_running::<{closure@$DIR/newtype_pair_retagging.rs:LL:CC}>` --> $DIR/newtype_pair_retagging.rs:LL:CC | LL | dealloc(); diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr index f76b6a57eaca0..6cbc6a86c091a 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr @@ -24,7 +24,7 @@ note: inside closure | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ -note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>` +note: inside `dealloc_while_running::<{closure@$DIR/newtype_retagging.rs:LL:CC}>` --> $DIR/newtype_retagging.rs:LL:CC | LL | dealloc(); diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr index 687c72d574d0d..d21ec9eddc2f7 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr @@ -6,7 +6,7 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag is foreign to the protected tag (i.e., it is not a child) - = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Frozen) to become Disabled + = help: this deallocation (acting as a foreign write access) would cause the protected tag (currently Reserved (conflicted)) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/newtype_retagging.rs:LL:CC @@ -18,12 +18,12 @@ help: the protected tag was created here, in the initial state Reserved | LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { | ^^ -help: the protected tag later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] +help: the protected tag later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4] --> $DIR/newtype_retagging.rs:LL:CC | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^ - = help: this transition corresponds to a loss of write permissions + = help: this transition corresponds to a temporary loss of write permissions until function exit = note: BACKTRACE (of the first span): = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC @@ -35,7 +35,7 @@ note: inside closure | LL | || drop(Box::from_raw(ptr)), | ^^^^^^^^^^^^^^^^^^^^^^^^ -note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>` +note: inside `dealloc_while_running::<{closure@$DIR/newtype_retagging.rs:LL:CC}>` --> $DIR/newtype_retagging.rs:LL:CC | LL | dealloc(); diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs deleted file mode 100644 index f192e76de1350..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.rs +++ /dev/null @@ -1,29 +0,0 @@ -//@revisions: stack tree -//@compile-flags: -Zmiri-preemption-rate=0 -//@[tree]compile-flags: -Zmiri-tree-borrows -use std::thread; - -#[derive(Copy, Clone)] -struct SendPtr(*mut i32); -unsafe impl Send for SendPtr {} - -fn main() { - let mut mem = 0; - let ptr = SendPtr(&mut mem as *mut _); - - let t = thread::spawn(move || { - let ptr = ptr; - // We do a protected 2phase retag (but no write!) in this thread. - fn retag(_x: &mut i32) {} //~[tree]ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` - retag(unsafe { &mut *ptr.0 }); //~[stack]ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` - }); - - // We do a read in the main thread. - unsafe { ptr.0.read() }; - - // These two operations do not commute -- if the read happens after the retag, the retagged pointer - // gets frozen! So we want this to be considered UB so that we can still freely move the read around - // in this thread without worrying about reordering with retags in other threads. - - t.join().unwrap(); -} diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr deleted file mode 100644 index 173acf4b96c03..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.tree.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: Undefined Behavior: Data race detected between (1) Read on thread `main` and (2) Write on thread `` at ALLOC. (2) just happened here - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | fn retag(_x: &mut i32) {} - | ^^ Data race detected between (1) Read on thread `main` and (2) Write on thread `` at ALLOC. (2) just happened here - | -help: and (1) occurred earlier here - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | unsafe { ptr.0.read() }; - | ^^^^^^^^^^^^ - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE (of the first span): - = note: inside `main::{closure#0}::retag` at $DIR/retag_data_race_protected_read.rs:LL:CC -note: inside closure - --> $DIR/retag_data_race_protected_read.rs:LL:CC - | -LL | ... retag(unsafe { &mut *ptr.0 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -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/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 544cd575ada33..3d8ba68547bd1 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -19,11 +19,17 @@ LL | | let non_copy = S(42); LL | | LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/arg_inplace_mutate.rs:LL:CC | LL | unsafe { ptr.write(S(0)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/arg_inplace_mutate.rs:LL:CC + | +LL | unsafe { ptr.write(S(0)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index c33645bdd280a..7b1846a32dbc3 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -19,11 +19,17 @@ LL | | let non_copy = S(42); LL | | LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/arg_inplace_observe_during.rs:LL:CC | LL | x.0 = 0; | ^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/arg_inplace_observe_during.rs:LL:CC + | +LL | x.0 = 0; + | ^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr index f181f90abd3b8..507b459b718fd 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr @@ -1,3 +1,5 @@ +WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed. +If you have a use-case for it, please file an issue. thread 'main' panicked at $DIR/exported_symbol_bad_unwind1.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index e4821bc0bac23..4c477416416f1 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -14,7 +14,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index e4821bc0bac23..4c477416416f1 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -14,7 +14,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index 66c2fb8db19f0..deafbf0207725 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -19,11 +19,17 @@ LL | | let ptr = &raw mut x; LL | | } LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/return_pointer_aliasing.rs:LL:CC | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr index 443ee8643fc28..e1b40a6bc1839 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr @@ -19,11 +19,17 @@ LL | | let ptr = &raw mut _x; LL | | } LL | | } | |_____^ -help: the protected tag was created here, in the initial state Active +help: the protected tag was created here, in the initial state Reserved --> $DIR/return_pointer_aliasing2.rs:LL:CC | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> $DIR/return_pointer_aliasing2.rs:LL:CC + | +LL | unsafe { ptr.write(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference = note: BACKTRACE (of the first span): = note: inside `myfun` at $DIR/return_pointer_aliasing2.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs new file mode 100644 index 0000000000000..e98a3abadf59b --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.rs @@ -0,0 +1,30 @@ +//@only-target-x86_64 +#![allow(improper_ctypes_definitions)] +use std::arch::x86_64::*; +use std::mem::transmute; + +#[no_mangle] +#[target_feature(enable = "avx")] +pub unsafe extern "C" fn foo(_y: f32, x: __m256) -> __m256 { + x +} + +pub fn bar(x: __m256) -> __m256 { + // The first and second argument get mixed up here since caller + // and callee do not have the same feature flags. + // In Miri, we don't have a concept of "dynamically available feature flags", + // so this will always lead to an error due to calling a function that requires + // an unavailable feature. If we ever support dynamically available features, + // this will need some dedicated checks. + unsafe { foo(0.0, x) } //~ERROR: unavailable target features +} + +fn assert_eq_m256(a: __m256, b: __m256) { + unsafe { assert_eq!(transmute::<_, [f32; 8]>(a), transmute::<_, [f32; 8]>(b)) } +} + +fn main() { + let input = unsafe { transmute::<_, __m256>([1.0f32; 8]) }; + let copy = bar(input); + assert_eq_m256(input, copy); +} diff --git a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr new file mode 100644 index 0000000000000..ab3ff5fcdc12c --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: calling a function that requires unavailable target features: avx + --> $DIR/simd_feature_flag_difference.rs:LL:CC + | +LL | unsafe { foo(0.0, x) } + | ^^^^^^^^^^^ calling a function that requires unavailable target features: avx + | + = 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 `bar` at $DIR/simd_feature_flag_difference.rs:LL:CC +note: inside `main` + --> $DIR/simd_feature_flag_difference.rs:LL:CC + | +LL | let copy = bar(input); + | ^^^^^^^^^^ + +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/generator-pinned-moved.stderr b/src/tools/miri/tests/fail/generator-pinned-moved.stderr index e29e352e64b0d..4cb8450c6d57c 100644 --- a/src/tools/miri/tests/fail/generator-pinned-moved.stderr +++ b/src/tools/miri/tests/fail/generator-pinned-moved.stderr @@ -18,12 +18,12 @@ LL | }; // *deallocate* generator_iterator | ^ = note: BACKTRACE (of the first span): = note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC -note: inside ` as std::iter::Iterator>::next` +note: inside ` as std::iter::Iterator>::next` --> $DIR/generator-pinned-moved.rs:LL:CC | LL | match me.resume(()) { | ^^^^^^^^^^^^^ - = note: inside `> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC + = note: inside `> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC note: inside `main` --> $DIR/generator-pinned-moved.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr index 70e10e8dc48f9..c63cfe065530e 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -11,7 +11,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr index 56143b6c20536..f954c4e9712f3 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr @@ -11,7 +11,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr b/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr index 3bd2be03ea1ff..4e5a2dfba3429 100644 --- a/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr +++ b/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr @@ -1,3 +1,5 @@ +WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed. +If you have a use-case for it, please file an issue. error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/bad_miri_start_panic.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr index 18438c13b2118..c2d007e5729da 100644 --- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr @@ -11,9 +11,9 @@ LL | std::panic::catch_unwind(|| unwind()).unwrap_err(); = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside closure at $DIR/bad_unwind.rs:LL:CC - = note: inside `std::panicking::r#try::do_call::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::panicking::r#try::<(), [closure@$DIR/bad_unwind.rs:LL:CC]>` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::panic::catch_unwind::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panic.rs:LL:CC + = note: inside `std::panicking::r#try::do_call::<{closure@$DIR/bad_unwind.rs:LL:CC}, ()>` at RUSTLIB/std/src/panicking.rs:LL:CC + = note: inside `std::panicking::r#try::<(), {closure@$DIR/bad_unwind.rs:LL:CC}>` at RUSTLIB/std/src/panicking.rs:LL:CC + = note: inside `std::panic::catch_unwind::<{closure@$DIR/bad_unwind.rs:LL:CC}, ()>` at RUSTLIB/std/src/panic.rs:LL:CC note: inside `main` --> $DIR/bad_unwind.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index a39522c8a61ae..5de7b3cf92980 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -16,7 +16,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind_nobacktrace` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index 404777344d7a8..6bd7157031afd 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -12,7 +12,7 @@ LL | ABORT(); = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC note: inside `main` --> $DIR/panic_abort1.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index 5512d145c6b7d..1d828d2e0f5a8 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -12,7 +12,7 @@ LL | ABORT(); = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC note: inside `main` --> $DIR/panic_abort2.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index 9fdccd4e59e4b..5e43444572e36 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -12,7 +12,7 @@ LL | ABORT(); = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC note: inside `main` --> $DIR/panic_abort3.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 3c9557ca4ab61..12c4b857134c7 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -12,7 +12,7 @@ LL | ABORT(); = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC note: inside `main` --> $DIR/panic_abort4.rs:LL:CC diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr index 2385439c8a5f7..a1b9662961d04 100644 --- a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr +++ b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr @@ -8,11 +8,11 @@ LL | let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode a = help: or pass `-Zmiri-isolation-error=warn` to configure Miri to return an error code from isolated operations (if supported for that operation) and continue with a warning = note: BACKTRACE: = note: inside closure at RUSTLIB/std/src/sys/PLATFORM/fs.rs:LL:CC - = note: inside `std::sys::PLATFORM::cvt_r::` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC + = note: inside `std::sys::PLATFORM::cvt_r::` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::sys::PLATFORM::fs::File::open_c` at RUSTLIB/std/src/sys/PLATFORM/fs.rs:LL:CC = note: inside closure at RUSTLIB/std/src/sys/PLATFORM/fs.rs:LL:CC - = note: inside `std::sys::PLATFORM::small_c_string::run_with_cstr::` at RUSTLIB/std/src/sys/PLATFORM/small_c_string.rs:LL:CC - = note: inside `std::sys::PLATFORM::small_c_string::run_path_with_cstr::` at RUSTLIB/std/src/sys/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::PLATFORM::small_c_string::run_with_cstr::` at RUSTLIB/std/src/sys/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::PLATFORM::small_c_string::run_path_with_cstr::` at RUSTLIB/std/src/sys/PLATFORM/small_c_string.rs:LL:CC = note: inside `std::sys::PLATFORM::fs::File::open` at RUSTLIB/std/src/sys/PLATFORM/fs.rs:LL:CC = note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC = note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr index 8ebb35450e5fa..00ea6b27d4c92 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr @@ -17,7 +17,7 @@ note: inside closure | LL | drop(unsafe { Box::from_raw(raw) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: inside `<[closure@$DIR/deallocate_against_protector1.rs:LL:CC] as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC + = note: inside `<{closure@$DIR/deallocate_against_protector1.rs:LL:CC} as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC note: inside `inner` --> $DIR/deallocate_against_protector1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs new file mode 100644 index 0000000000000..670fe9858ed54 --- /dev/null +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.rs @@ -0,0 +1,30 @@ +//@compile-flags: -Zmiri-preemption-rate=0 +use std::thread; + +#[derive(Copy, Clone)] +struct SendPtr(*mut i32); +unsafe impl Send for SendPtr {} + +fn main() { + let mut mem = 0; + let ptr = SendPtr(&mut mem as *mut _); + + let t = thread::spawn(move || { + let ptr = ptr; + // We do a protected mutable retag (but no write!) in this thread. + fn retag(_x: &mut i32) {} + retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `` + }); + + // We do a read in the main thread. + unsafe { ptr.0.read() }; + + // These two operations do not commute! + // - In Stacked Borrows, if the read happens after the retag it will `Disable` the pointer. + // - In Tree Borrows, if the read happens after the retag, the retagged pointer gets frozen! + // Ideally we would want this to be considered UB so that we can still freely move the read around + // in this thread without worrying about reordering with retags in other threads, + // but in Tree Borrows we have found worse issues that occur if we make this a data race. + + t.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.stack.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr similarity index 100% rename from src/tools/miri/tests/fail/both_borrows/retag_data_race_protected_read.stack.stderr rename to src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index e9277ebdbfd3e..dc634df831f1f 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -16,7 +16,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index 769769d957dbe..fc92770ed165c 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├─┬── -| Re*| │ └─┬── -| Re*| │ └──── Strongly protected -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├─┬── +| RsM | │ └─┬── +| RsM | │ └──── Strongly protected +| RsM | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) is forbidden --> $DIR/cell-protected-write.rs:LL:CC @@ -16,14 +16,14 @@ LL | *y = 1; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag (y, callee:y, caller:y) is foreign to the protected tag (callee:x) (i.e., it is not a child) - = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved) to become Disabled + = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved (interior mutable)) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/cell-protected-write.rs:LL:CC | LL | let y = (&mut *n).get(); | ^^^^^^^^^ -help: the protected tag was created here, in the initial state Reserved +help: the protected tag was created here, in the initial state Reserved (interior mutable) --> $DIR/cell-protected-write.rs:LL:CC | LL | unsafe fn write_second(x: &mut UnsafeCell, y: *mut u8) { diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr index f7e9fb9e3c3a4..4b4b8f24a68f5 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Res| │ └──── Strongly protected -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| Rs | │ └──── Strongly protected +| Rs | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) is forbidden --> $DIR/int-protected-write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs b/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs new file mode 100644 index 0000000000000..3f39dcb4b76ad --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/spurious_read.rs @@ -0,0 +1,117 @@ +// We ensure a deterministic execution. +// Note that we are *also* using barriers: the barriers enforce the +// specific interleaving of operations that we want, but only the preemption +// rate guarantees that the error message is also deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +//@compile-flags: -Zmiri-tree-borrows + +use std::sync::{Arc, Barrier}; +use std::thread; + +// A way to send raw pointers across threads. +// Note that when using this in closures will require explicit copying +// `let ptr = ptr;` to force the borrow checker to copy the `Send` wrapper +// instead of just copying the inner `!Send` field. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +fn main() { + retagx_retagy_retx_writey_rety(); +} + +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +// Interleaving: +// retag x (protect) +// retag y (protect) +// spurious read x (target only, which we are *not* executing) +// ret x +// write y +// ret y +// +// This is an interleaving that will never *not* have UB in the target +// (`noalias` violation on `y`). +// For the spurious read to be allowed, we need to ensure there *is* UB +// in the source (i.e., without the spurious read). +// +// The interleaving differs from the one in `tests/pass/tree_borrows/spurious_read.rs` only +// in that it has the `write y` while `y` is still protected. +// When the write occurs after protection ends, both source and target are fine +// (checked by the `pass` test); when the write occurs during protection, both source +// and target are UB (checked by this test). +fn retagx_retagy_retx_writey_rety() { + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // This thread only needs to + // - retag `x` protected + // - do a read through `x` + // - remove `x`'s protector + // Most of the complexity here is synchronization. + let thread_x = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn as_mut(x: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "retag y (&mut, protect)"); + synchronized!(b, "location where spurious read of x would happen in the target"); + // This is ensuring taht we have UB *without* the spurious read, + // so we don't read here. + synchronized!(b, "ret x"); + synchronized!(b, "write y"); + let x = x as *mut u8; + x + } + let _x = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "end"); + }); + + // This thread's job is to + // - retag `y` protected + // - (wait for the other thread to return so that there is no foreign protector when we write) + // - attempt a write through `y`. + // - (UB should have occured by now, but the next step would be to + // remove `y`'s protector) + let thread_y = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "retag y (&mut, protect)"); + fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "location where spurious read of x would happen in the target"); + synchronized!(b, "ret x"); + let y = y as *mut u8; + synchronized!(b, "write y"); + unsafe { + *y = 2; //~ERROR: /write access through .* is forbidden/ + } + synchronized!(b, "ret y"); + y + } + let _y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "end"); + }); + + thread_x.join().unwrap(); + thread_y.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr new file mode 100644 index 0000000000000..99ffb84933901 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr @@ -0,0 +1,44 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: retag y (&mut, protect) +Thread 2 executing: retag y (&mut, protect) +Thread 2 executing: location where spurious read of x would happen in the target +Thread 1 executing: location where spurious read of x would happen in the target +Thread 1 executing: ret x +Thread 2 executing: ret x +Thread 2 executing: write y +Thread 1 executing: write y +Thread 1 executing: ret y +error: Undefined Behavior: write access through is forbidden + --> $DIR/spurious_read.rs:LL:CC + | +LL | *y = 2; + | ^^^^^^ write access through is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Reserved (conflicted) which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/spurious_read.rs:LL:CC + | +LL | fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Reserved (conflicted) due to a protector release (acting as a foreign read access) on every location previously accessed by this tag + --> $DIR/spurious_read.rs:LL:CC + | +LL | } + | ^ + = help: this transition corresponds to a temporary loss of write permissions until function exit + = note: BACKTRACE (of the first span): + = note: inside `retagx_retagy_retx_writey_rety::{closure#1}::as_mut` at $DIR/spurious_read.rs:LL:CC +note: inside closure + --> $DIR/spurious_read.rs:LL:CC + | +LL | let _y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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/tree_borrows/strongly-protected.stderr b/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr index 55665e63e8a7e..fb2e77f9d2aa2 100644 --- a/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr @@ -28,7 +28,7 @@ note: inside closure | LL | drop(unsafe { Box::from_raw(raw) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: inside `<[closure@$DIR/strongly-protected.rs:LL:CC] as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC + = note: inside `<{closure@$DIR/strongly-protected.rs:LL:CC} as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC note: inside `inner` --> $DIR/strongly-protected.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index cf94dbb990906..7575300bc575c 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -14,7 +14,7 @@ LL | ABORT(); = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC + = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index ebfeb863abfd9..82c49cfb17c5a 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -3,6 +3,7 @@ #![feature(io_error_more)] use std::fs::{remove_file, File}; +use std::mem::transmute; use std::os::unix::io::AsRawFd; use std::path::PathBuf; @@ -375,6 +376,18 @@ fn test_sigrt() { assert!(max - min >= 8) } +fn test_dlsym() { + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"notasymbol\0".as_ptr().cast()) }; + assert!(addr as usize == 0); + + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"isatty\0".as_ptr().cast()) }; + assert!(addr as usize != 0); + let isatty: extern "C" fn(i32) -> i32 = unsafe { transmute(addr) }; + assert_eq!(isatty(999), 0); + let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); + assert_eq!(errno, libc::EBADF); +} + fn main() { test_posix_gettimeofday(); test_posix_mkstemp(); @@ -387,6 +400,7 @@ fn main() { test_isatty(); test_clocks(); + test_dlsym(); test_memcpy(); test_strcpy(); diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs index 5cd12959ca40e..8d3173da400f8 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.rs @@ -41,6 +41,8 @@ fn main() { eprintln!("{}", out); // Print the 'main' frame (and everything before it) to stdout, skipping // the printing of internal (and possibly fragile) libstd frames. + // Stdout is less normalized so we see more, but it also means we can print less + // as platform differences would lead to test suite failures. if !seen_main { println!("{}", out); seen_main = name == "main"; diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr index ee556b3e4a05a..bc24d6de734db 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stderr @@ -2,4 +2,17 @@ $DIR/backtrace-api-v0.rs:LL:CC (func_d) $DIR/backtrace-api-v0.rs:LL:CC (func_c) $DIR/backtrace-api-v0.rs:LL:CC (func_b) $DIR/backtrace-api-v0.rs:LL:CC (func_a) -$DIR/backtrace-api-v0.rs:LL:CC RUSTLIB/core/src/ops/function.rs:LL:CC (>::call_once - RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC (std::sys_common::backtrace::__rust_begin_short_backtrace) +$DIR/backtrace-api-v0.rs:LL:CC (main) +RUSTLIB/core/src/ops/function.rs:LL:CC (>::call_once - shim(fn())) +RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC (std::sys_common::backtrace::__rust_begin_short_backtrace) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start::{closure#0}) +RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try) +RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#2}) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try) +RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start) diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout index 2fe31dd0e6bae..c9cab268168c9 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v0.stdout @@ -1,5 +1,5 @@ $DIR/backtrace-api-v0.rs:24:14 (func_d) $DIR/backtrace-api-v0.rs:20:5 (func_c) -$DIR/backtrace-api-v0.rs:9:5 (func_b) +$DIR/backtrace-api-v0.rs:9:5 (func_b::) $DIR/backtrace-api-v0.rs:5:5 (func_a) $DIR/backtrace-api-v0.rs:29:18 (main) diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.rs b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.rs index 1e35574b39b6c..ad05271ca519b 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.rs +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.rs @@ -54,6 +54,8 @@ fn main() { eprintln!("{}", out); // Print the 'main' frame (and everything before it) to stdout, skipping // the printing of internal (and possibly fragile) libstd frames. + // Stdout is less normalized so we see more, but it also means we can print less + // as platform differences would lead to test suite failures. if !seen_main { println!("{}", out); seen_main = name == "main"; diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr index 7dc281af31ddc..246e54becd820 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr @@ -2,4 +2,17 @@ $DIR/backtrace-api-v1.rs:LL:CC (func_d) $DIR/backtrace-api-v1.rs:LL:CC (func_c) $DIR/backtrace-api-v1.rs:LL:CC (func_b) $DIR/backtrace-api-v1.rs:LL:CC (func_a) -$DIR/backtrace-api-v1.rs:LL:CC RUSTLIB/core/src/ops/function.rs:LL:CC (>::call_once - RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC (std::sys_common::backtrace::__rust_begin_short_backtrace) +$DIR/backtrace-api-v1.rs:LL:CC (main) +RUSTLIB/core/src/ops/function.rs:LL:CC (>::call_once - shim(fn())) +RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC (std::sys_common::backtrace::__rust_begin_short_backtrace) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start::{closure#0}) +RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try) +RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#2}) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call) +RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try) +RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal) +RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start) diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stdout b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stdout index 0d2ae3b516a87..e145c167e880e 100644 --- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stdout +++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stdout @@ -1,5 +1,5 @@ $DIR/backtrace-api-v1.rs:27:9 (func_d) $DIR/backtrace-api-v1.rs:20:5 (func_c) -$DIR/backtrace-api-v1.rs:9:5 (func_b) +$DIR/backtrace-api-v1.rs:9:5 (func_b::) $DIR/backtrace-api-v1.rs:5:5 (func_a) $DIR/backtrace-api-v1.rs:34:18 (main) diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index fee5ca44ffb34..70c64485fe937 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -168,6 +168,16 @@ fn basic() { let x: u32 = unsafe { std::mem::transmute(42.0_f32) }; let y: f32 = unsafe { std::mem::transmute(x) }; assert_eq(y, 42.0_f32); + + // `%` sign behavior, some of this used to be buggy + assert!((black_box(1.0f32) % 1.0).is_sign_positive()); + assert!((black_box(1.0f32) % -1.0).is_sign_positive()); + assert!((black_box(-1.0f32) % 1.0).is_sign_negative()); + assert!((black_box(-1.0f32) % -1.0).is_sign_negative()); + assert!((black_box(1.0f64) % 1.0).is_sign_positive()); + assert!((black_box(1.0f64) % -1.0).is_sign_positive()); + assert!((black_box(-1.0f64) % 1.0).is_sign_negative()); + assert!((black_box(-1.0f64) % -1.0).is_sign_negative()); } /// Many of these test values are taken from diff --git a/src/tools/miri/tests/pass/function_calls/disable_abi_check.stderr b/src/tools/miri/tests/pass/function_calls/disable_abi_check.stderr new file mode 100644 index 0000000000000..e5b84f6d7090e --- /dev/null +++ b/src/tools/miri/tests/pass/function_calls/disable_abi_check.stderr @@ -0,0 +1,2 @@ +WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed. +If you have a use-case for it, please file an issue. diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs index b66826e3fcdfb..1c99a96feda94 100644 --- a/src/tools/miri/tests/pass/function_pointers.rs +++ b/src/tools/miri/tests/pass/function_pointers.rs @@ -23,6 +23,10 @@ fn h(i: i32, j: i32) -> i32 { j * i * 7 } +fn i() -> i32 { + 73 +} + fn return_fn_ptr(f: fn() -> i32) -> fn() -> i32 { f } @@ -72,10 +76,18 @@ fn main() { assert_eq!(indirect3(h), 210); assert_eq!(indirect_mut3(h), 210); assert_eq!(indirect_once3(h), 210); - let g = f as fn() -> i32; - assert!(return_fn_ptr(g) == g); - assert!(return_fn_ptr(g) as unsafe fn() -> i32 == g as fn() -> i32 as unsafe fn() -> i32); - assert!(return_fn_ptr(f) != f); + // Check that `i` always has the same address. This is not guaranteed + // but Miri currently uses a fixed address for monomorphic functions. + assert!(return_fn_ptr(i) == i); + assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32); + // We don't check anything for `f`. Miri gives it many different addresses + // but mir-opts can turn them into the same address. + let _val = return_fn_ptr(f) != f; + // However, if we only turn `f` into a function pointer and use that pointer, + // it is equal to itself. + let f2 = f as fn() -> i32; + assert!(return_fn_ptr(f2) == f2); + assert!(return_fn_ptr(f2) as unsafe fn() -> i32 == f2 as fn() -> i32 as unsafe fn() -> i32); // Any non-null value is okay for function pointers. unsafe { diff --git a/src/tools/miri/tests/pass/intrinsics-math.rs b/src/tools/miri/tests/pass/intrinsics-math.rs index e0e4f5654d6a4..5f7730a3e86af 100644 --- a/src/tools/miri/tests/pass/intrinsics-math.rs +++ b/src/tools/miri/tests/pass/intrinsics-math.rs @@ -1,4 +1,5 @@ #![feature(float_gamma)] +use std::{f32, f64}; macro_rules! assert_approx_eq { ($a:expr, $b:expr) => {{ @@ -15,8 +16,7 @@ fn ldexp(a: f64, b: i32) -> f64 { } pub fn main() { - use std::f32; - use std::f64; + mul_add(); assert_approx_eq!(64f32.sqrt(), 8f32); assert_approx_eq!(64f64.sqrt(), 8f64); @@ -48,13 +48,6 @@ pub fn main() { assert_approx_eq!(8f32.log2(), 3f32); assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E); - assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0); - assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E); - assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0); - assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); - assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY); - assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY); - assert_approx_eq!((-1.0f32).abs(), 1.0f32); assert_approx_eq!(34.2f64.abs(), 34.2f64); @@ -146,3 +139,19 @@ pub fn main() { assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln()); assert_eq!(sign, -1); } + +fn mul_add() { + assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0); + assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E); + assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0); + assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); + assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY); + assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY); + + let f = f32::mul_add( + -0.000000000000000000000000000000000000014728589, + 0.0000037105144, + 0.000000000000000000000000000000000000000000055, + ); + assert_eq!(f.to_bits(), f32::to_bits(-0.0)); +} diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs new file mode 100644 index 0000000000000..c38158dc797ca --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs @@ -0,0 +1,217 @@ +// Ignore everything except x86 and x86_64 +// Any additional target are added to CI should be ignored here +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq + +#![feature(avx512_target_feature)] +#![feature(stdsimd)] + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::mem::transmute; + +fn main() { + assert!(is_x86_feature_detected!("avx512f")); + assert!(is_x86_feature_detected!("avx512vl")); + assert!(is_x86_feature_detected!("avx512bitalg")); + assert!(is_x86_feature_detected!("avx512vpopcntdq")); + + unsafe { + test_avx512bitalg(); + test_avx512vpopcntdq(); + } +} + +// Some of the constants in the tests below are just bit patterns. They should not +// be interpreted as integers; signedness does not make sense for them, but +// __mXXXi happens to be defined in terms of signed integers. +#[allow(overflowing_literals)] +#[target_feature(enable = "avx512bitalg,avx512f,avx512vl")] +unsafe fn test_avx512bitalg() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs + + #[target_feature(enable = "avx512bitalg,avx512f")] + unsafe fn test_mm512_popcnt_epi16() { + let test_data = _mm512_set_epi16( + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1_FF, 0x3_FF, 0x7_FF, 0xF_FF, 0x1F_FF, + 0x3F_FF, 0x7F_FF, 0xFF_FF, -1, -100, 255, 256, 2, 4, 8, 16, 32, 64, 128, 256, 512, + 1024, 2048, + ); + let actual_result = _mm512_popcnt_epi16(test_data); + let reference_result = _mm512_set_epi16( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 12, 8, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, + ); + assert_eq_m512i(actual_result, reference_result); + } + test_mm512_popcnt_epi16(); + + #[target_feature(enable = "avx512bitalg,avx512f,avx512vl")] + unsafe fn test_mm256_popcnt_epi16() { + let test_data = _mm256_set_epi16( + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1_FF, 0x3_FF, 0x7_FF, 0xF_FF, 0x1F_FF, + 0x3F_FF, 0x7F_FF, + ); + let actual_result = _mm256_popcnt_epi16(test_data); + let reference_result = + _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(actual_result, reference_result); + } + test_mm256_popcnt_epi16(); + + #[target_feature(enable = "avx512bitalg,avx512f,avx512vl")] + unsafe fn test_mm_popcnt_epi16() { + let test_data = _mm_set_epi16(0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F); + let actual_result = _mm_popcnt_epi16(test_data); + let reference_result = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(actual_result, reference_result); + } + test_mm_popcnt_epi16(); + + #[target_feature(enable = "avx512bitalg,avx512f")] + unsafe fn test_mm512_popcnt_epi8() { + let test_data = _mm512_set_epi8( + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, -1, 2, 4, 8, 16, 32, 64, 128, 171, 206, 100, + 217, 109, 253, 190, 177, 254, 179, 215, 230, 68, 201, 172, 183, 154, 84, 56, 227, 189, + 140, 35, 117, 219, 169, 226, 170, 13, 22, 159, 251, 73, 121, 143, 145, 85, 91, 137, 90, + 225, 21, 249, 211, 155, 228, 70, + ); + let actual_result = _mm512_popcnt_epi8(test_data); + let reference_result = _mm512_set_epi8( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 1, 1, 1, 1, 1, 1, 1, 5, 5, 3, 5, 5, 7, 6, 4, 7, 5, 6, 5, + 2, 4, 4, 6, 4, 3, 3, 5, 6, 3, 3, 5, 6, 4, 4, 4, 3, 3, 6, 7, 3, 5, 5, 3, 4, 5, 3, 4, 4, + 3, 6, 5, 5, 4, 3, + ); + assert_eq_m512i(actual_result, reference_result); + } + test_mm512_popcnt_epi8(); + + #[target_feature(enable = "avx512bitalg,avx512f,avx512vl")] + unsafe fn test_mm256_popcnt_epi8() { + let test_data = _mm256_set_epi8( + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, -1, 2, 4, 8, 16, 32, 64, 128, 171, 206, 100, + 217, 109, 253, 190, 177, 254, 179, 215, 230, 68, 201, 172, + ); + let actual_result = _mm256_popcnt_epi8(test_data); + let reference_result = _mm256_set_epi8( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 1, 1, 1, 1, 1, 1, 1, 5, 5, 3, 5, 5, 7, 6, 4, 7, 5, 6, 5, + 2, 4, 4, + ); + assert_eq_m256i(actual_result, reference_result); + } + test_mm256_popcnt_epi8(); + + #[target_feature(enable = "avx512bitalg,avx512f,avx512vl")] + unsafe fn test_mm_popcnt_epi8() { + let test_data = + _mm_set_epi8(0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, -1, 2, 4, 8, 16, 32, 64); + let actual_result = _mm_popcnt_epi8(test_data); + let reference_result = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 1, 1, 1, 1, 1, 1); + assert_eq_m128i(actual_result, reference_result); + } + test_mm_popcnt_epi8(); +} + +#[target_feature(enable = "avx512vpopcntdq,avx512f,avx512vl")] +unsafe fn test_avx512vpopcntdq() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86/avx512vpopcntdq.rs + + #[target_feature(enable = "avx512vpopcntdq,avx512f")] + unsafe fn test_mm512_popcnt_epi32() { + let test_data = _mm512_set_epi32( + 0, + 1, + -1, + 2, + 7, + 0xFF_FE, + 0x7F_FF_FF_FF, + -100, + 0x40_00_00_00, + 103, + 371, + 552, + 432_948, + 818_826_998, + 255, + 256, + ); + let actual_result = _mm512_popcnt_epi32(test_data); + let reference_result = + _mm512_set_epi32(0, 1, 32, 1, 3, 15, 31, 28, 1, 5, 6, 3, 10, 17, 8, 1); + assert_eq_m512i(actual_result, reference_result); + } + test_mm512_popcnt_epi32(); + + #[target_feature(enable = "avx512vpopcntdq,avx512f,avx512vl")] + unsafe fn test_mm256_popcnt_epi32() { + let test_data = _mm256_set_epi32(0, 1, -1, 2, 7, 0xFF_FE, 0x7F_FF_FF_FF, -100); + let actual_result = _mm256_popcnt_epi32(test_data); + let reference_result = _mm256_set_epi32(0, 1, 32, 1, 3, 15, 31, 28); + assert_eq_m256i(actual_result, reference_result); + } + test_mm256_popcnt_epi32(); + + #[target_feature(enable = "avx512vpopcntdq,avx512f,avx512vl")] + unsafe fn test_mm_popcnt_epi32() { + let test_data = _mm_set_epi32(0, 1, -1, -100); + let actual_result = _mm_popcnt_epi32(test_data); + let reference_result = _mm_set_epi32(0, 1, 32, 28); + assert_eq_m128i(actual_result, reference_result); + } + test_mm_popcnt_epi32(); + + #[target_feature(enable = "avx512vpopcntdq,avx512f")] + unsafe fn test_mm512_popcnt_epi64() { + let test_data = _mm512_set_epi64(0, 1, -1, 2, 7, 0xFF_FE, 0x7F_FF_FF_FF_FF_FF_FF_FF, -100); + let actual_result = _mm512_popcnt_epi64(test_data); + let reference_result = _mm512_set_epi64(0, 1, 64, 1, 3, 15, 63, 60); + assert_eq_m512i(actual_result, reference_result); + } + test_mm512_popcnt_epi64(); + + #[target_feature(enable = "avx512vpopcntdq,avx512vl")] + unsafe fn test_mm256_popcnt_epi64() { + let test_data = _mm256_set_epi64x(0, 1, -1, -100); + let actual_result = _mm256_popcnt_epi64(test_data); + let reference_result = _mm256_set_epi64x(0, 1, 64, 60); + assert_eq_m256i(actual_result, reference_result); + } + test_mm256_popcnt_epi64(); + + #[target_feature(enable = "avx512vpopcntdq,avx512vl")] + unsafe fn test_mm_popcnt_epi64() { + let test_data = _mm_set_epi64x(0, 1); + let actual_result = _mm_popcnt_epi64(test_data); + let reference_result = _mm_set_epi64x(0, 1); + assert_eq_m128i(actual_result, reference_result); + let test_data = _mm_set_epi64x(-1, -100); + let actual_result = _mm_popcnt_epi64(test_data); + let reference_result = _mm_set_epi64x(64, 60); + assert_eq_m128i(actual_result, reference_result); + } + test_mm_popcnt_epi64(); +} + +#[track_caller] +unsafe fn assert_eq_m512i(a: __m512i, b: __m512i) { + assert_eq!(transmute::<_, [i32; 16]>(a), transmute::<_, [i32; 16]>(b)) +} + +#[track_caller] +unsafe fn assert_eq_m256i(a: __m256i, b: __m256i) { + assert_eq!(transmute::<_, [u64; 4]>(a), transmute::<_, [u64; 4]>(b)) +} + +#[track_caller] +unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) { + assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b)) +} diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse.rs index 9b1ded94b5d40..a62a5ee3781b7 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse.rs @@ -1,1094 +1,1107 @@ -// Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here -//@ignore-target-aarch64 -//@ignore-target-arm -//@ignore-target-avr -//@ignore-target-s390x -//@ignore-target-thumbv7em -//@ignore-target-wasm32 - -#[cfg(target_arch = "x86")] -use std::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use std::arch::x86_64::*; -use std::f32::NAN; -use std::mem::transmute; - fn main() { - assert!(is_x86_feature_detected!("sse")); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + assert!(is_x86_feature_detected!("sse")); - unsafe { - test_sse(); + unsafe { + tests::test_sse(); + } } } -macro_rules! assert_approx_eq { - ($a:expr, $b:expr, $eps:expr) => {{ - let (a, b) = (&$a, &$b); - assert!( - (*a - *b).abs() < $eps, - "assertion failed: `(left !== right)` \ +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod tests { + #[cfg(target_arch = "x86")] + use std::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::*; + use std::f32::NAN; + use std::mem::transmute; + + macro_rules! assert_approx_eq { + ($a:expr, $b:expr, $eps:expr) => {{ + let (a, b) = (&$a, &$b); + assert!( + (*a - *b).abs() < $eps, + "assertion failed: `(left !== right)` \ (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)", - *a, - *b, - $eps, - (*a - *b).abs() - ); - }}; -} - -#[target_feature(enable = "sse")] -unsafe fn test_sse() { - // Mostly copied from library/stdarch/crates/core_arch/src/x86{,_64}/sse.rs - - #[target_feature(enable = "sse")] - unsafe fn assert_eq_m128(a: __m128, b: __m128) { - let r = _mm_cmpeq_ps(a, b); - if _mm_movemask_ps(r) != 0b1111 { - panic!("{:?} != {:?}", a, b); - } - } - - #[target_feature(enable = "sse")] - unsafe fn test_mm_add_ss() { - let a = _mm_set_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_set_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_add_ss(a, b); - assert_eq_m128(r, _mm_set_ps(-1.0, 5.0, 0.0, -15.0)); - } - test_mm_add_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_sub_ss() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_sub_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(99.0, 5.0, 0.0, -10.0)); - } - test_mm_sub_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_mul_ss() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_mul_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(100.0, 5.0, 0.0, -10.0)); - } - test_mm_mul_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_div_ss() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_div_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(0.01, 5.0, 0.0, -10.0)); - } - test_mm_div_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_sqrt_ss() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_sqrt_ss(a); - let e = _mm_setr_ps(2.0, 13.0, 16.0, 100.0); - assert_eq_m128(r, e); - } - test_mm_sqrt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_sqrt_ps() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_sqrt_ps(a); - let e = _mm_setr_ps(2.0, 3.6055512, 4.0, 10.0); - assert_eq_m128(r, e); + *a, + *b, + $eps, + (*a - *b).abs() + ); + }}; } - test_mm_sqrt_ps(); #[target_feature(enable = "sse")] - unsafe fn test_mm_rcp_ss() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_rcp_ss(a); - let e = _mm_setr_ps(0.24993896, 13.0, 16.0, 100.0); - let rel_err = 0.00048828125; - - let r: [f32; 4] = transmute(r); - let e: [f32; 4] = transmute(e); - assert_approx_eq!(r[0], e[0], 2. * rel_err); - for i in 1..4 { - assert_eq!(r[i], e[i]); + pub(super) unsafe fn test_sse() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86{,_64}/sse.rs + + #[target_feature(enable = "sse")] + unsafe fn assert_eq_m128(a: __m128, b: __m128) { + let r = _mm_cmpeq_ps(a, b); + if _mm_movemask_ps(r) != 0b1111 { + panic!("{:?} != {:?}", a, b); + } } - } - test_mm_rcp_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_rcp_ps() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_rcp_ps(a); - let e = _mm_setr_ps(0.24993896, 0.0769043, 0.06248474, 0.0099983215); - let rel_err = 0.00048828125; - - let r: [f32; 4] = transmute(r); - let e: [f32; 4] = transmute(e); - for i in 0..4 { - assert_approx_eq!(r[i], e[i], 2. * rel_err); + #[target_feature(enable = "sse")] + unsafe fn test_mm_add_ss() { + let a = _mm_set_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_set_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_add_ss(a, b); + assert_eq_m128(r, _mm_set_ps(-1.0, 5.0, 0.0, -15.0)); } - } - test_mm_rcp_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_rsqrt_ss() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_rsqrt_ss(a); - let e = _mm_setr_ps(0.49987793, 13.0, 16.0, 100.0); - let rel_err = 0.00048828125; - - let r: [f32; 4] = transmute(r); - let e: [f32; 4] = transmute(e); - assert_approx_eq!(r[0], e[0], 2. * rel_err); - for i in 1..4 { - assert_eq!(r[i], e[i]); + test_mm_add_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_sub_ss() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_sub_ss(a, b); + assert_eq_m128(r, _mm_setr_ps(99.0, 5.0, 0.0, -10.0)); } - } - test_mm_rsqrt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_rsqrt_ps() { - let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); - let r = _mm_rsqrt_ps(a); - let e = _mm_setr_ps(0.49987793, 0.2772827, 0.24993896, 0.099990845); - let rel_err = 0.00048828125; - - let r: [f32; 4] = transmute(r); - let e: [f32; 4] = transmute(e); - for i in 0..4 { - assert_approx_eq!(r[i], e[i], 2. * rel_err); + test_mm_sub_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_mul_ss() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_mul_ss(a, b); + assert_eq_m128(r, _mm_setr_ps(100.0, 5.0, 0.0, -10.0)); } - } - test_mm_rsqrt_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_min_ss() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_min_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(-100.0, 5.0, 0.0, -10.0)); - } - test_mm_min_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_min_ps() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_min_ps(a, b); - assert_eq_m128(r, _mm_setr_ps(-100.0, 5.0, 0.0, -10.0)); - - // `_mm_min_ps` can **not** be implemented using the `simd_min` rust intrinsic because - // the semantics of `simd_min` are different to those of `_mm_min_ps` regarding handling - // of `-0.0`. - let a = _mm_setr_ps(-0.0, 0.0, 0.0, 0.0); - let b = _mm_setr_ps(0.0, 0.0, 0.0, 0.0); - let r1: [u8; 16] = transmute(_mm_min_ps(a, b)); - let r2: [u8; 16] = transmute(_mm_min_ps(b, a)); - let a: [u8; 16] = transmute(a); - let b: [u8; 16] = transmute(b); - assert_eq!(r1, b); - assert_eq!(r2, a); - assert_ne!(a, b); // sanity check that -0.0 is actually present - } - test_mm_min_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_max_ss() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_max_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(-1.0, 5.0, 0.0, -10.0)); - } - test_mm_max_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_max_ps() { - let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); - let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); - let r = _mm_max_ps(a, b); - assert_eq_m128(r, _mm_setr_ps(-1.0, 20.0, 0.0, -5.0)); - - // `_mm_max_ps` can **not** be implemented using the `simd_max` rust intrinsic because - // the semantics of `simd_max` are different to those of `_mm_max_ps` regarding handling - // of `-0.0`. - let a = _mm_setr_ps(-0.0, 0.0, 0.0, 0.0); - let b = _mm_setr_ps(0.0, 0.0, 0.0, 0.0); - let r1: [u8; 16] = transmute(_mm_max_ps(a, b)); - let r2: [u8; 16] = transmute(_mm_max_ps(b, a)); - let a: [u8; 16] = transmute(a); - let b: [u8; 16] = transmute(b); - assert_eq!(r1, b); - assert_eq!(r2, a); - assert_ne!(a, b); // sanity check that -0.0 is actually present - } - test_mm_max_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpeq_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(-1.0, 5.0, 6.0, 7.0); - let r: [u32; 4] = transmute(_mm_cmpeq_ss(a, b)); - let e: [u32; 4] = transmute(_mm_setr_ps(transmute(0u32), 2.0, 3.0, 4.0)); - assert_eq!(r, e); - - let b2 = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let r2: [u32; 4] = transmute(_mm_cmpeq_ss(a, b2)); - let e2: [u32; 4] = transmute(_mm_setr_ps(transmute(0xffffffffu32), 2.0, 3.0, 4.0)); - assert_eq!(r2, e2); - } - test_mm_cmpeq_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmplt_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = 0u32; // a.extract(0) < b.extract(0) - let c1 = 0u32; // a.extract(0) < c.extract(0) - let d1 = !0u32; // a.extract(0) < d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmplt_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmplt_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmplt_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmplt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmple_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = 0u32; // a.extract(0) <= b.extract(0) - let c1 = !0u32; // a.extract(0) <= c.extract(0) - let d1 = !0u32; // a.extract(0) <= d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmple_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmple_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmple_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmple_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpgt_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) > b.extract(0) - let c1 = 0u32; // a.extract(0) > c.extract(0) - let d1 = 0u32; // a.extract(0) > d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpgt_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpgt_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpgt_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpgt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpge_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) >= b.extract(0) - let c1 = !0u32; // a.extract(0) >= c.extract(0) - let d1 = 0u32; // a.extract(0) >= d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpge_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpge_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpge_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpge_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpneq_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) != b.extract(0) - let c1 = 0u32; // a.extract(0) != c.extract(0) - let d1 = !0u32; // a.extract(0) != d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpneq_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpneq_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpneq_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpneq_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnlt_ss() { - // TODO: this test is exactly the same as for `_mm_cmpge_ss`, but there - // must be a difference. It may have to do with behavior in the - // presence of NaNs (signaling or quiet). If so, we should add tests - // for those. - - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) >= b.extract(0) - let c1 = !0u32; // a.extract(0) >= c.extract(0) - let d1 = 0u32; // a.extract(0) >= d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpnlt_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpnlt_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpnlt_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpnlt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnle_ss() { - // TODO: this test is exactly the same as for `_mm_cmpgt_ss`, but there - // must be a difference. It may have to do with behavior in the - // presence - // of NaNs (signaling or quiet). If so, we should add tests for those. - - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) > b.extract(0) - let c1 = 0u32; // a.extract(0) > c.extract(0) - let d1 = 0u32; // a.extract(0) > d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpnle_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpnle_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpnle_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpnle_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpngt_ss() { - // TODO: this test is exactly the same as for `_mm_cmple_ss`, but there - // must be a difference. It may have to do with behavior in the - // presence of NaNs (signaling or quiet). If so, we should add tests - // for those. - - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = 0u32; // a.extract(0) <= b.extract(0) - let c1 = !0u32; // a.extract(0) <= c.extract(0) - let d1 = !0u32; // a.extract(0) <= d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpngt_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpngt_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpngt_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpngt_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnge_ss() { - // TODO: this test is exactly the same as for `_mm_cmplt_ss`, but there - // must be a difference. It may have to do with behavior in the - // presence of NaNs (signaling or quiet). If so, we should add tests - // for those. - - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = 0u32; // a.extract(0) < b.extract(0) - let c1 = 0u32; // a.extract(0) < c.extract(0) - let d1 = !0u32; // a.extract(0) < d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpnge_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpnge_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpnge_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpnge_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpord_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(NAN, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = !0u32; // a.extract(0) ord b.extract(0) - let c1 = 0u32; // a.extract(0) ord c.extract(0) - let d1 = !0u32; // a.extract(0) ord d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpord_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpord_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpord_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpord_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpunord_ss() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); - let c = _mm_setr_ps(NAN, 5.0, 6.0, 7.0); - let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); - - let b1 = 0u32; // a.extract(0) unord b.extract(0) - let c1 = !0u32; // a.extract(0) unord c.extract(0) - let d1 = 0u32; // a.extract(0) unord d.extract(0) - - let rb: [u32; 4] = transmute(_mm_cmpunord_ss(a, b)); - let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); - assert_eq!(rb, eb); - - let rc: [u32; 4] = transmute(_mm_cmpunord_ss(a, c)); - let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); - assert_eq!(rc, ec); - - let rd: [u32; 4] = transmute(_mm_cmpunord_ss(a, d)); - let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); - assert_eq!(rd, ed); - } - test_mm_cmpunord_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpeq_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, fls, tru, fls]; - let r: [u32; 4] = transmute(_mm_cmpeq_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpeq_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmplt_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, fls, fls, fls]; - let r: [u32; 4] = transmute(_mm_cmplt_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmplt_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmple_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, 4.0); - let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, fls, tru, fls]; - let r: [u32; 4] = transmute(_mm_cmple_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmple_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpgt_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 42.0); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, tru, fls, fls]; - let r: [u32; 4] = transmute(_mm_cmpgt_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpgt_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpge_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 42.0); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, tru, tru, fls]; - let r: [u32; 4] = transmute(_mm_cmpge_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpge_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpneq_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, tru, fls, tru]; - let r: [u32; 4] = transmute(_mm_cmpneq_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpneq_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnlt_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, tru, tru, tru]; - let r: [u32; 4] = transmute(_mm_cmpnlt_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpnlt_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnle_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, tru, fls, tru]; - let r: [u32; 4] = transmute(_mm_cmpnle_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpnle_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpngt_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, fls, tru, tru]; - let r: [u32; 4] = transmute(_mm_cmpngt_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpngt_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpnge_ps() { - let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); - let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, fls, fls, tru]; - let r: [u32; 4] = transmute(_mm_cmpnge_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpnge_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpord_ps() { - let a = _mm_setr_ps(10.0, 50.0, NAN, NAN); - let b = _mm_setr_ps(15.0, NAN, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [tru, fls, fls, fls]; - let r: [u32; 4] = transmute(_mm_cmpord_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpord_ps(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cmpunord_ps() { - let a = _mm_setr_ps(10.0, 50.0, NAN, NAN); - let b = _mm_setr_ps(15.0, NAN, 1.0, NAN); - let tru = !0u32; - let fls = 0u32; - - let e = [fls, tru, tru, tru]; - let r: [u32; 4] = transmute(_mm_cmpunord_ps(a, b)); - assert_eq!(r, e); - } - test_mm_cmpunord_ps(); + test_mm_mul_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_div_ss() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_div_ss(a, b); + assert_eq_m128(r, _mm_setr_ps(0.01, 5.0, 0.0, -10.0)); + } + test_mm_div_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_sqrt_ss() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_sqrt_ss(a); + let e = _mm_setr_ps(2.0, 13.0, 16.0, 100.0); + assert_eq_m128(r, e); + } + test_mm_sqrt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_sqrt_ps() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_sqrt_ps(a); + let e = _mm_setr_ps(2.0, 3.6055512, 4.0, 10.0); + assert_eq_m128(r, e); + } + test_mm_sqrt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_rcp_ss() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_rcp_ss(a); + let e = _mm_setr_ps(0.24993896, 13.0, 16.0, 100.0); + let rel_err = 0.00048828125; + + let r: [f32; 4] = transmute(r); + let e: [f32; 4] = transmute(e); + assert_approx_eq!(r[0], e[0], 2. * rel_err); + for i in 1..4 { + assert_eq!(r[i], e[i]); + } + } + test_mm_rcp_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_rcp_ps() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_rcp_ps(a); + let e = _mm_setr_ps(0.24993896, 0.0769043, 0.06248474, 0.0099983215); + let rel_err = 0.00048828125; + + let r: [f32; 4] = transmute(r); + let e: [f32; 4] = transmute(e); + for i in 0..4 { + assert_approx_eq!(r[i], e[i], 2. * rel_err); + } + } + test_mm_rcp_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_rsqrt_ss() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_rsqrt_ss(a); + let e = _mm_setr_ps(0.49987793, 13.0, 16.0, 100.0); + let rel_err = 0.00048828125; + + let r: [f32; 4] = transmute(r); + let e: [f32; 4] = transmute(e); + assert_approx_eq!(r[0], e[0], 2. * rel_err); + for i in 1..4 { + assert_eq!(r[i], e[i]); + } + } + test_mm_rsqrt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_rsqrt_ps() { + let a = _mm_setr_ps(4.0, 13.0, 16.0, 100.0); + let r = _mm_rsqrt_ps(a); + let e = _mm_setr_ps(0.49987793, 0.2772827, 0.24993896, 0.099990845); + let rel_err = 0.00048828125; + + let r: [f32; 4] = transmute(r); + let e: [f32; 4] = transmute(e); + for i in 0..4 { + assert_approx_eq!(r[i], e[i], 2. * rel_err); + } + } + test_mm_rsqrt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_min_ss() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_min_ss(a, b); + assert_eq_m128(r, _mm_setr_ps(-100.0, 5.0, 0.0, -10.0)); + } + test_mm_min_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_min_ps() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_min_ps(a, b); + assert_eq_m128(r, _mm_setr_ps(-100.0, 5.0, 0.0, -10.0)); + + // `_mm_min_ps` can **not** be implemented using the `simd_min` rust intrinsic because + // the semantics of `simd_min` are different to those of `_mm_min_ps` regarding handling + // of `-0.0`. + let a = _mm_setr_ps(-0.0, 0.0, 0.0, 0.0); + let b = _mm_setr_ps(0.0, 0.0, 0.0, 0.0); + let r1: [u8; 16] = transmute(_mm_min_ps(a, b)); + let r2: [u8; 16] = transmute(_mm_min_ps(b, a)); + let a: [u8; 16] = transmute(a); + let b: [u8; 16] = transmute(b); + assert_eq!(r1, b); + assert_eq!(r2, a); + assert_ne!(a, b); // sanity check that -0.0 is actually present + } + test_mm_min_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_max_ss() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_max_ss(a, b); + assert_eq_m128(r, _mm_setr_ps(-1.0, 5.0, 0.0, -10.0)); + } + test_mm_max_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_max_ps() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_max_ps(a, b); + assert_eq_m128(r, _mm_setr_ps(-1.0, 20.0, 0.0, -5.0)); + + // `_mm_max_ps` can **not** be implemented using the `simd_max` rust intrinsic because + // the semantics of `simd_max` are different to those of `_mm_max_ps` regarding handling + // of `-0.0`. + let a = _mm_setr_ps(-0.0, 0.0, 0.0, 0.0); + let b = _mm_setr_ps(0.0, 0.0, 0.0, 0.0); + let r1: [u8; 16] = transmute(_mm_max_ps(a, b)); + let r2: [u8; 16] = transmute(_mm_max_ps(b, a)); + let a: [u8; 16] = transmute(a); + let b: [u8; 16] = transmute(b); + assert_eq!(r1, b); + assert_eq!(r2, a); + assert_ne!(a, b); // sanity check that -0.0 is actually present + } + test_mm_max_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpeq_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(-1.0, 5.0, 6.0, 7.0); + let r: [u32; 4] = transmute(_mm_cmpeq_ss(a, b)); + let e: [u32; 4] = transmute(_mm_setr_ps(transmute(0u32), 2.0, 3.0, 4.0)); + assert_eq!(r, e); + + let b2 = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let r2: [u32; 4] = transmute(_mm_cmpeq_ss(a, b2)); + let e2: [u32; 4] = transmute(_mm_setr_ps(transmute(0xffffffffu32), 2.0, 3.0, 4.0)); + assert_eq!(r2, e2); + } + test_mm_cmpeq_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmplt_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = 0u32; // a.extract(0) < b.extract(0) + let c1 = 0u32; // a.extract(0) < c.extract(0) + let d1 = !0u32; // a.extract(0) < d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmplt_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmplt_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmplt_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmplt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmple_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = 0u32; // a.extract(0) <= b.extract(0) + let c1 = !0u32; // a.extract(0) <= c.extract(0) + let d1 = !0u32; // a.extract(0) <= d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmple_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmple_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmple_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmple_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpgt_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) > b.extract(0) + let c1 = 0u32; // a.extract(0) > c.extract(0) + let d1 = 0u32; // a.extract(0) > d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpgt_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpgt_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpgt_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpgt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpge_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) >= b.extract(0) + let c1 = !0u32; // a.extract(0) >= c.extract(0) + let d1 = 0u32; // a.extract(0) >= d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpge_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpge_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpge_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpge_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpneq_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) != b.extract(0) + let c1 = 0u32; // a.extract(0) != c.extract(0) + let d1 = !0u32; // a.extract(0) != d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpneq_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpneq_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpneq_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpneq_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnlt_ss() { + // TODO: this test is exactly the same as for `_mm_cmpge_ss`, but there + // must be a difference. It may have to do with behavior in the + // presence of NaNs (signaling or quiet). If so, we should add tests + // for those. + + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) >= b.extract(0) + let c1 = !0u32; // a.extract(0) >= c.extract(0) + let d1 = 0u32; // a.extract(0) >= d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpnlt_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpnlt_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpnlt_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpnlt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnle_ss() { + // TODO: this test is exactly the same as for `_mm_cmpgt_ss`, but there + // must be a difference. It may have to do with behavior in the + // presence + // of NaNs (signaling or quiet). If so, we should add tests for those. + + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) > b.extract(0) + let c1 = 0u32; // a.extract(0) > c.extract(0) + let d1 = 0u32; // a.extract(0) > d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpnle_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpnle_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpnle_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpnle_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpngt_ss() { + // TODO: this test is exactly the same as for `_mm_cmple_ss`, but there + // must be a difference. It may have to do with behavior in the + // presence of NaNs (signaling or quiet). If so, we should add tests + // for those. + + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = 0u32; // a.extract(0) <= b.extract(0) + let c1 = !0u32; // a.extract(0) <= c.extract(0) + let d1 = !0u32; // a.extract(0) <= d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpngt_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpngt_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpngt_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpngt_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnge_ss() { + // TODO: this test is exactly the same as for `_mm_cmplt_ss`, but there + // must be a difference. It may have to do with behavior in the + // presence of NaNs (signaling or quiet). If so, we should add tests + // for those. + + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(1.0, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = 0u32; // a.extract(0) < b.extract(0) + let c1 = 0u32; // a.extract(0) < c.extract(0) + let d1 = !0u32; // a.extract(0) < d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpnge_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpnge_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpnge_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpnge_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpord_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(NAN, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = !0u32; // a.extract(0) ord b.extract(0) + let c1 = 0u32; // a.extract(0) ord c.extract(0) + let d1 = !0u32; // a.extract(0) ord d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpord_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpord_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpord_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpord_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpunord_ss() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(0.0, 5.0, 6.0, 7.0); + let c = _mm_setr_ps(NAN, 5.0, 6.0, 7.0); + let d = _mm_setr_ps(2.0, 5.0, 6.0, 7.0); + + let b1 = 0u32; // a.extract(0) unord b.extract(0) + let c1 = !0u32; // a.extract(0) unord c.extract(0) + let d1 = 0u32; // a.extract(0) unord d.extract(0) + + let rb: [u32; 4] = transmute(_mm_cmpunord_ss(a, b)); + let eb: [u32; 4] = transmute(_mm_setr_ps(transmute(b1), 2.0, 3.0, 4.0)); + assert_eq!(rb, eb); + + let rc: [u32; 4] = transmute(_mm_cmpunord_ss(a, c)); + let ec: [u32; 4] = transmute(_mm_setr_ps(transmute(c1), 2.0, 3.0, 4.0)); + assert_eq!(rc, ec); + + let rd: [u32; 4] = transmute(_mm_cmpunord_ss(a, d)); + let ed: [u32; 4] = transmute(_mm_setr_ps(transmute(d1), 2.0, 3.0, 4.0)); + assert_eq!(rd, ed); + } + test_mm_cmpunord_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpeq_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, fls, tru, fls]; + let r: [u32; 4] = transmute(_mm_cmpeq_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpeq_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmplt_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, fls, fls, fls]; + let r: [u32; 4] = transmute(_mm_cmplt_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmplt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmple_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, 4.0); + let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, fls, tru, fls]; + let r: [u32; 4] = transmute(_mm_cmple_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmple_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpgt_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 42.0); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, tru, fls, fls]; + let r: [u32; 4] = transmute(_mm_cmpgt_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpgt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpge_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 42.0); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, tru, tru, fls]; + let r: [u32; 4] = transmute(_mm_cmpge_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpge_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpneq_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, tru, fls, tru]; + let r: [u32; 4] = transmute(_mm_cmpneq_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpneq_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnlt_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, tru, tru, tru]; + let r: [u32; 4] = transmute(_mm_cmpnlt_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpnlt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnle_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, tru, fls, tru]; + let r: [u32; 4] = transmute(_mm_cmpnle_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpnle_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpngt_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, fls, tru, tru]; + let r: [u32; 4] = transmute(_mm_cmpngt_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpngt_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpnge_ps() { + let a = _mm_setr_ps(10.0, 50.0, 1.0, NAN); + let b = _mm_setr_ps(15.0, 20.0, 1.0, 5.0); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, fls, fls, tru]; + let r: [u32; 4] = transmute(_mm_cmpnge_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpnge_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpord_ps() { + let a = _mm_setr_ps(10.0, 50.0, NAN, NAN); + let b = _mm_setr_ps(15.0, NAN, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [tru, fls, fls, fls]; + let r: [u32; 4] = transmute(_mm_cmpord_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpord_ps(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cmpunord_ps() { + let a = _mm_setr_ps(10.0, 50.0, NAN, NAN); + let b = _mm_setr_ps(15.0, NAN, 1.0, NAN); + let tru = !0u32; + let fls = 0u32; + + let e = [fls, tru, tru, tru]; + let r: [u32; 4] = transmute(_mm_cmpunord_ps(a, b)); + assert_eq!(r, e); + } + test_mm_cmpunord_ps(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_comieq_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_comieq_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 0, 0, 0]; + let ee = &[1i32, 0, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_comieq_ss(a, b); + let r = _mm_comieq_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_comieq_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_comieq_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_comieq_ss(); + test_mm_comieq_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_comilt_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_comilt_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[0i32, 1, 0, 0]; + let ee = &[0i32, 1, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_comilt_ss(a, b); + let r = _mm_comilt_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_comilt_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_comilt_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_comilt_ss(); + test_mm_comilt_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_comile_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_comile_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 1, 0, 0]; + let ee = &[1i32, 1, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_comile_ss(a, b); + let r = _mm_comile_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_comile_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_comile_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_comile_ss(); + test_mm_comile_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_comigt_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_comigt_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 0, 1, 0]; + let ee = &[1i32, 0, 1, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_comige_ss(a, b); + let r = _mm_comige_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_comige_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_comige_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_comigt_ss(); + test_mm_comigt_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_comineq_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_comineq_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[0i32, 1, 1, 1]; + let ee = &[0i32, 1, 1, 1]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_comineq_ss(a, b); + let r = _mm_comineq_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_comineq_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_comineq_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_comineq_ss(); + test_mm_comineq_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomieq_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomieq_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 0, 0, 0]; + let ee = &[1i32, 0, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomieq_ss(a, b); + let r = _mm_ucomieq_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomieq_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomieq_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomieq_ss(); + test_mm_ucomieq_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomilt_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomilt_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[0i32, 1, 0, 0]; + let ee = &[0i32, 1, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomilt_ss(a, b); + let r = _mm_ucomilt_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomilt_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomilt_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomilt_ss(); + test_mm_ucomilt_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomile_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomile_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 1, 0, 0]; + let ee = &[1i32, 1, 0, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomile_ss(a, b); + let r = _mm_ucomile_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomile_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomile_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomile_ss(); + test_mm_ucomile_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomigt_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomigt_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[0i32, 0, 1, 0]; + let ee = &[0i32, 0, 1, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomigt_ss(a, b); + let r = _mm_ucomigt_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomigt_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomigt_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomigt_ss(); + test_mm_ucomigt_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomige_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomige_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[1i32, 0, 1, 0]; + let ee = &[1i32, 0, 1, 0]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomige_ss(a, b); + let r = _mm_ucomige_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomige_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomige_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomige_ss(); + test_mm_ucomige_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_ucomineq_ss() { - let aa = &[3.0f32, 12.0, 23.0, NAN]; - let bb = &[3.0f32, 47.5, 1.5, NAN]; + #[target_feature(enable = "sse")] + unsafe fn test_mm_ucomineq_ss() { + let aa = &[3.0f32, 12.0, 23.0, NAN]; + let bb = &[3.0f32, 47.5, 1.5, NAN]; - let ee = &[0i32, 1, 1, 1]; + let ee = &[0i32, 1, 1, 1]; - for i in 0..4 { - let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); - let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); + for i in 0..4 { + let a = _mm_setr_ps(aa[i], 1.0, 2.0, 3.0); + let b = _mm_setr_ps(bb[i], 0.0, 2.0, 4.0); - let r = _mm_ucomineq_ss(a, b); + let r = _mm_ucomineq_ss(a, b); - assert_eq!( - ee[i], r, - "_mm_ucomineq_ss({:?}, {:?}) = {}, expected: {} (i={})", - a, b, r, ee[i], i - ); + assert_eq!( + ee[i], r, + "_mm_ucomineq_ss({:?}, {:?}) = {}, expected: {} (i={})", + a, b, r, ee[i], i + ); + } } - } - test_mm_ucomineq_ss(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvtss_si32() { - let inputs = &[42.0f32, -3.1, 4.0e10, 4.0e-20, NAN, 2147483500.1]; - let result = &[42i32, -3, i32::MIN, 0, i32::MIN, 2147483520]; - for i in 0..inputs.len() { - let x = _mm_setr_ps(inputs[i], 1.0, 3.0, 4.0); - let e = result[i]; - let r = _mm_cvtss_si32(x); - assert_eq!(e, r, "TestCase #{} _mm_cvtss_si32({:?}) = {}, expected: {}", i, x, r, e); + test_mm_ucomineq_ss(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvtss_si32() { + let inputs = &[42.0f32, -3.1, 4.0e10, 4.0e-20, NAN, 2147483500.1]; + let result = &[42i32, -3, i32::MIN, 0, i32::MIN, 2147483520]; + for i in 0..inputs.len() { + let x = _mm_setr_ps(inputs[i], 1.0, 3.0, 4.0); + let e = result[i]; + let r = _mm_cvtss_si32(x); + assert_eq!( + e, r, + "TestCase #{} _mm_cvtss_si32({:?}) = {}, expected: {}", + i, x, r, e + ); + } } - } - test_mm_cvtss_si32(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvttss_si32() { - let inputs = &[ - (42.0f32, 42i32), - (-31.4, -31), - (-33.5, -33), - (-34.5, -34), - (10.999, 10), - (-5.99, -5), - (4.0e10, i32::MIN), - (4.0e-10, 0), - (NAN, i32::MIN), - (2147483500.1, 2147483520), - ]; - for i in 0..inputs.len() { - let (xi, e) = inputs[i]; - let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); - let r = _mm_cvttss_si32(x); - assert_eq!(e, r, "TestCase #{} _mm_cvttss_si32({:?}) = {}, expected: {}", i, x, r, e); + test_mm_cvtss_si32(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvttss_si32() { + let inputs = &[ + (42.0f32, 42i32), + (-31.4, -31), + (-33.5, -33), + (-34.5, -34), + (10.999, 10), + (-5.99, -5), + (4.0e10, i32::MIN), + (4.0e-10, 0), + (NAN, i32::MIN), + (2147483500.1, 2147483520), + ]; + for i in 0..inputs.len() { + let (xi, e) = inputs[i]; + let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); + let r = _mm_cvttss_si32(x); + assert_eq!( + e, r, + "TestCase #{} _mm_cvttss_si32({:?}) = {}, expected: {}", + i, x, r, e + ); + } } - } - test_mm_cvttss_si32(); - - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvtss_f32() { - let a = _mm_setr_ps(312.0134, 5.0, 6.0, 7.0); - assert_eq!(_mm_cvtss_f32(a), 312.0134); - } - test_mm_cvtss_f32(); + test_mm_cvttss_si32(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvtsi32_ss() { - let inputs = &[ - (4555i32, 4555.0f32), - (322223333, 322223330.0), - (-432, -432.0), - (-322223333, -322223330.0), - ]; - - for i in 0..inputs.len() { - let (x, f) = inputs[i]; - let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0); - let r = _mm_cvtsi32_ss(a, x); - let e = _mm_setr_ps(f, 6.0, 7.0, 8.0); - assert_eq_m128(e, r); + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvtss_f32() { + let a = _mm_setr_ps(312.0134, 5.0, 6.0, 7.0); + assert_eq!(_mm_cvtss_f32(a), 312.0134); } - } - test_mm_cvtsi32_ss(); - - // Intrinsic only available on x86_64 - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvtss_si64() { - let inputs = &[ - (42.0f32, 42i64), - (-31.4, -31), - (-33.5, -34), - (-34.5, -34), - (4.0e10, 40_000_000_000), - (4.0e-10, 0), - (f32::NAN, i64::MIN), - (2147483500.1, 2147483520), - (9.223371e18, 9223370937343148032), - ]; - for i in 0..inputs.len() { - let (xi, e) = inputs[i]; - let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); - let r = _mm_cvtss_si64(x); - assert_eq!(e, r, "TestCase #{} _mm_cvtss_si64({:?}) = {}, expected: {}", i, x, r, e); + test_mm_cvtss_f32(); + + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvtsi32_ss() { + let inputs = &[ + (4555i32, 4555.0f32), + (322223333, 322223330.0), + (-432, -432.0), + (-322223333, -322223330.0), + ]; + + for i in 0..inputs.len() { + let (x, f) = inputs[i]; + let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0); + let r = _mm_cvtsi32_ss(a, x); + let e = _mm_setr_ps(f, 6.0, 7.0, 8.0); + assert_eq_m128(e, r); + } } - } - #[cfg(target_arch = "x86_64")] - test_mm_cvtss_si64(); - - // Intrinsic only available on x86_64 - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvttss_si64() { - let inputs = &[ - (42.0f32, 42i64), - (-31.4, -31), - (-33.5, -33), - (-34.5, -34), - (10.999, 10), - (-5.99, -5), - (4.0e10, 40_000_000_000), - (4.0e-10, 0), - (f32::NAN, i64::MIN), - (2147483500.1, 2147483520), - (9.223371e18, 9223370937343148032), - (9.223372e18, i64::MIN), - ]; - for i in 0..inputs.len() { - let (xi, e) = inputs[i]; - let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); - let r = _mm_cvttss_si64(x); - assert_eq!(e, r, "TestCase #{} _mm_cvttss_si64({:?}) = {}, expected: {}", i, x, r, e); + test_mm_cvtsi32_ss(); + + // Intrinsic only available on x86_64 + #[cfg(target_arch = "x86_64")] + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvtss_si64() { + let inputs = &[ + (42.0f32, 42i64), + (-31.4, -31), + (-33.5, -34), + (-34.5, -34), + (4.0e10, 40_000_000_000), + (4.0e-10, 0), + (f32::NAN, i64::MIN), + (2147483500.1, 2147483520), + (9.223371e18, 9223370937343148032), + ]; + for i in 0..inputs.len() { + let (xi, e) = inputs[i]; + let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); + let r = _mm_cvtss_si64(x); + assert_eq!( + e, r, + "TestCase #{} _mm_cvtss_si64({:?}) = {}, expected: {}", + i, x, r, e + ); + } } - } - #[cfg(target_arch = "x86_64")] - test_mm_cvttss_si64(); - - // Intrinsic only available on x86_64 - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "sse")] - unsafe fn test_mm_cvtsi64_ss() { - let inputs = &[ - (4555i64, 4555.0f32), - (322223333, 322223330.0), - (-432, -432.0), - (-322223333, -322223330.0), - (9223372036854775807, 9.223372e18), - (-9223372036854775808, -9.223372e18), - ]; - - for i in 0..inputs.len() { - let (x, f) = inputs[i]; - let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0); - let r = _mm_cvtsi64_ss(a, x); - let e = _mm_setr_ps(f, 6.0, 7.0, 8.0); - assert_eq_m128(e, r); + #[cfg(target_arch = "x86_64")] + test_mm_cvtss_si64(); + + // Intrinsic only available on x86_64 + #[cfg(target_arch = "x86_64")] + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvttss_si64() { + let inputs = &[ + (42.0f32, 42i64), + (-31.4, -31), + (-33.5, -33), + (-34.5, -34), + (10.999, 10), + (-5.99, -5), + (4.0e10, 40_000_000_000), + (4.0e-10, 0), + (f32::NAN, i64::MIN), + (2147483500.1, 2147483520), + (9.223371e18, 9223370937343148032), + (9.223372e18, i64::MIN), + ]; + for i in 0..inputs.len() { + let (xi, e) = inputs[i]; + let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0); + let r = _mm_cvttss_si64(x); + assert_eq!( + e, r, + "TestCase #{} _mm_cvttss_si64({:?}) = {}, expected: {}", + i, x, r, e + ); + } } - } - #[cfg(target_arch = "x86_64")] - test_mm_cvtsi64_ss(); + #[cfg(target_arch = "x86_64")] + test_mm_cvttss_si64(); + + // Intrinsic only available on x86_64 + #[cfg(target_arch = "x86_64")] + #[target_feature(enable = "sse")] + unsafe fn test_mm_cvtsi64_ss() { + let inputs = &[ + (4555i64, 4555.0f32), + (322223333, 322223330.0), + (-432, -432.0), + (-322223333, -322223330.0), + (9223372036854775807, 9.223372e18), + (-9223372036854775808, -9.223372e18), + ]; + + for i in 0..inputs.len() { + let (x, f) = inputs[i]; + let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0); + let r = _mm_cvtsi64_ss(a, x); + let e = _mm_setr_ps(f, 6.0, 7.0, 8.0); + assert_eq_m128(e, r); + } + } + #[cfg(target_arch = "x86_64")] + test_mm_cvtsi64_ss(); - #[target_feature(enable = "sse")] - unsafe fn test_mm_movemask_ps() { - let r = _mm_movemask_ps(_mm_setr_ps(-1.0, 5.0, -5.0, 0.0)); - assert_eq!(r, 0b0101); + #[target_feature(enable = "sse")] + unsafe fn test_mm_movemask_ps() { + let r = _mm_movemask_ps(_mm_setr_ps(-1.0, 5.0, -5.0, 0.0)); + assert_eq!(r, 0b0101); - let r = _mm_movemask_ps(_mm_setr_ps(-1.0, -5.0, -5.0, 0.0)); - assert_eq!(r, 0b0111); + let r = _mm_movemask_ps(_mm_setr_ps(-1.0, -5.0, -5.0, 0.0)); + assert_eq!(r, 0b0111); + } + test_mm_movemask_ps(); + + let x = 0i8; + _mm_prefetch(&x, _MM_HINT_T0); + _mm_prefetch(&x, _MM_HINT_T1); + _mm_prefetch(&x, _MM_HINT_T2); + _mm_prefetch(&x, _MM_HINT_NTA); + _mm_prefetch(&x, _MM_HINT_ET0); + _mm_prefetch(&x, _MM_HINT_ET1); } - test_mm_movemask_ps(); - - let x = 0i8; - _mm_prefetch(&x, _MM_HINT_T0); - _mm_prefetch(&x, _MM_HINT_T1); - _mm_prefetch(&x, _MM_HINT_T2); - _mm_prefetch(&x, _MM_HINT_NTA); - _mm_prefetch(&x, _MM_HINT_ET0); - _mm_prefetch(&x, _MM_HINT_ET1); } diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs index 1b55a94783aa5..2c7665bc73631 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs @@ -1,828 +1,843 @@ -// Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here -//@ignore-target-aarch64 -//@ignore-target-arm -//@ignore-target-avr -//@ignore-target-s390x -//@ignore-target-thumbv7em -//@ignore-target-wasm32 - -#[cfg(target_arch = "x86")] -use std::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use std::arch::x86_64::*; -use std::f64::NAN; -use std::mem::transmute; - fn main() { - assert!(is_x86_feature_detected!("sse2")); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + assert!(is_x86_feature_detected!("sse2")); - unsafe { - test_sse2(); + unsafe { + tests::test_sse2(); + } } } -#[target_feature(enable = "sse2")] -unsafe fn _mm_setr_epi64x(a: i64, b: i64) -> __m128i { - _mm_set_epi64x(b, a) -} - -#[target_feature(enable = "sse2")] -unsafe fn test_sse2() { - // Mostly copied from library/stdarch/crates/core_arch/src/x86{,_64}/sse2.rs +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod tests { + #[cfg(target_arch = "x86")] + use std::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::*; + use std::f64::NAN; + use std::mem::transmute; + #[target_feature(enable = "sse2")] unsafe fn _mm_setr_epi64x(a: i64, b: i64) -> __m128i { _mm_set_epi64x(b, a) } - #[track_caller] - #[target_feature(enable = "sse")] - unsafe fn assert_eq_m128(a: __m128, b: __m128) { - let r = _mm_cmpeq_ps(a, b); - if _mm_movemask_ps(r) != 0b1111 { - panic!("{:?} != {:?}", a, b); + #[target_feature(enable = "sse2")] + pub(super) unsafe fn test_sse2() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86{,_64}/sse2.rs + + unsafe fn _mm_setr_epi64x(a: i64, b: i64) -> __m128i { + _mm_set_epi64x(b, a) } - } - #[track_caller] - #[target_feature(enable = "sse2")] - unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) { - assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b)) - } + #[track_caller] + #[target_feature(enable = "sse")] + unsafe fn assert_eq_m128(a: __m128, b: __m128) { + let r = _mm_cmpeq_ps(a, b); + if _mm_movemask_ps(r) != 0b1111 { + panic!("{:?} != {:?}", a, b); + } + } - #[track_caller] - #[target_feature(enable = "sse2")] - unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) { - if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 { - panic!("{:?} != {:?}", a, b); + #[track_caller] + #[target_feature(enable = "sse2")] + unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) { + assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b)) } - } - #[target_feature(enable = "sse2")] - unsafe fn test_mm_avg_epu8() { - let (a, b) = (_mm_set1_epi8(3), _mm_set1_epi8(9)); - let r = _mm_avg_epu8(a, b); - assert_eq_m128i(r, _mm_set1_epi8(6)); - } - test_mm_avg_epu8(); + #[track_caller] + #[target_feature(enable = "sse2")] + unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) { + if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 { + panic!("{:?} != {:?}", a, b); + } + } - #[target_feature(enable = "sse2")] - unsafe fn test_mm_avg_epu16() { - let (a, b) = (_mm_set1_epi16(3), _mm_set1_epi16(9)); - let r = _mm_avg_epu16(a, b); - assert_eq_m128i(r, _mm_set1_epi16(6)); - } - test_mm_avg_epu16(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_avg_epu8() { + let (a, b) = (_mm_set1_epi8(3), _mm_set1_epi8(9)); + let r = _mm_avg_epu8(a, b); + assert_eq_m128i(r, _mm_set1_epi8(6)); + } + test_mm_avg_epu8(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_mulhi_epi16() { - let (a, b) = (_mm_set1_epi16(1000), _mm_set1_epi16(-1001)); - let r = _mm_mulhi_epi16(a, b); - assert_eq_m128i(r, _mm_set1_epi16(-16)); - } - test_mm_mulhi_epi16(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_avg_epu16() { + let (a, b) = (_mm_set1_epi16(3), _mm_set1_epi16(9)); + let r = _mm_avg_epu16(a, b); + assert_eq_m128i(r, _mm_set1_epi16(6)); + } + test_mm_avg_epu16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_madd_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm_madd_epi16(a, b); + let e = _mm_setr_epi32(29, 81, 149, 233); + assert_eq_m128i(r, e); + + let a = + _mm_setr_epi16(i16::MAX, i16::MAX, i16::MIN, i16::MIN, i16::MIN, i16::MAX, 0, 0); + let b = + _mm_setr_epi16(i16::MAX, i16::MAX, i16::MIN, i16::MIN, i16::MAX, i16::MIN, 0, 0); + let r = _mm_madd_epi16(a, b); + let e = _mm_setr_epi32(0x7FFE0002, i32::MIN, -0x7FFF0000, 0); + assert_eq_m128i(r, e); + } + test_mm_madd_epi16(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_mulhi_epu16() { - let (a, b) = (_mm_set1_epi16(1000), _mm_set1_epi16(1001)); - let r = _mm_mulhi_epu16(a, b); - assert_eq_m128i(r, _mm_set1_epi16(15)); - } - test_mm_mulhi_epu16(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_mulhi_epi16() { + let (a, b) = (_mm_set1_epi16(1000), _mm_set1_epi16(-1001)); + let r = _mm_mulhi_epi16(a, b); + assert_eq_m128i(r, _mm_set1_epi16(-16)); + } + test_mm_mulhi_epi16(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_mul_epu32() { - let a = _mm_setr_epi64x(1_000_000_000, 1 << 34); - let b = _mm_setr_epi64x(1_000_000_000, 1 << 35); - let r = _mm_mul_epu32(a, b); - let e = _mm_setr_epi64x(1_000_000_000 * 1_000_000_000, 0); - assert_eq_m128i(r, e); - } - test_mm_mul_epu32(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_mulhi_epu16() { + let (a, b) = (_mm_set1_epi16(1000), _mm_set1_epi16(1001)); + let r = _mm_mulhi_epu16(a, b); + assert_eq_m128i(r, _mm_set1_epi16(15)); + } + test_mm_mulhi_epu16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_mul_epu32() { + let a = _mm_setr_epi64x(1_000_000_000, 1 << 34); + let b = _mm_setr_epi64x(1_000_000_000, 1 << 35); + let r = _mm_mul_epu32(a, b); + let e = _mm_setr_epi64x(1_000_000_000 * 1_000_000_000, 0); + assert_eq_m128i(r, e); + } + test_mm_mul_epu32(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sad_epu8() { - #[rustfmt::skip] + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sad_epu8() { + #[rustfmt::skip] let a = _mm_setr_epi8( 255u8 as i8, 254u8 as i8, 253u8 as i8, 252u8 as i8, 1, 2, 3, 4, 155u8 as i8, 154u8 as i8, 153u8 as i8, 152u8 as i8, 1, 2, 3, 4, ); - let b = _mm_setr_epi8(0, 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2); - let r = _mm_sad_epu8(a, b); - let e = _mm_setr_epi64x(1020, 614); - assert_eq_m128i(r, e); - } - test_mm_sad_epu8(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sll_epi16() { - let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); - let r = _mm_sll_epi16(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i( - r, - _mm_setr_epi16(0xCC0, -0xCC0, 0xDD0, -0xDD0, 0xEE0, -0xEE0, 0xFF0, -0xFF0), - ); - let r = _mm_sll_epi16(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_sll_epi16(a, _mm_set_epi64x(0, 16)); - assert_eq_m128i(r, _mm_set1_epi16(0)); - let r = _mm_sll_epi16(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi16(0)); - } - test_mm_sll_epi16(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_srl_epi16() { - let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); - let r = _mm_srl_epi16(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_setr_epi16(0xC, 0xFF3, 0xD, 0xFF2, 0xE, 0xFF1, 0xF, 0xFF0)); - let r = _mm_srl_epi16(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_srl_epi16(a, _mm_set_epi64x(0, 16)); - assert_eq_m128i(r, _mm_set1_epi16(0)); - let r = _mm_srl_epi16(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi16(0)); - } - test_mm_srl_epi16(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sra_epi16() { - let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); - let r = _mm_sra_epi16(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_setr_epi16(0xC, -0xD, 0xD, -0xE, 0xE, -0xF, 0xF, -0x10)); - let r = _mm_sra_epi16(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_sra_epi16(a, _mm_set_epi64x(0, 16)); - assert_eq_m128i(r, _mm_setr_epi16(0, -1, 0, -1, 0, -1, 0, -1)); - let r = _mm_sra_epi16(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_setr_epi16(0, -1, 0, -1, 0, -1, 0, -1)); - } - test_mm_sra_epi16(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sll_epi32() { - let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); - let r = _mm_sll_epi32(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_setr_epi32(0xEEEE0, -0xEEEE0, 0xFFFF0, -0xFFFF0)); - let r = _mm_sll_epi32(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_sll_epi32(a, _mm_set_epi64x(0, 32)); - assert_eq_m128i(r, _mm_set1_epi32(0)); - let r = _mm_sll_epi32(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi32(0)); - } - test_mm_sll_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_srl_epi32() { - let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); - let r = _mm_srl_epi32(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_setr_epi32(0xEEE, 0xFFFF111, 0xFFF, 0xFFFF000)); - let r = _mm_srl_epi32(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_srl_epi32(a, _mm_set_epi64x(0, 32)); - assert_eq_m128i(r, _mm_set1_epi32(0)); - let r = _mm_srl_epi32(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi32(0)); - } - test_mm_srl_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sra_epi32() { - let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); - let r = _mm_sra_epi32(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_setr_epi32(0xEEE, -0xEEF, 0xFFF, -0x1000)); - let r = _mm_sra_epi32(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_sra_epi32(a, _mm_set_epi64x(0, 32)); - assert_eq_m128i(r, _mm_setr_epi32(0, -1, 0, -1)); - let r = _mm_sra_epi32(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_setr_epi32(0, -1, 0, -1)); - } - test_mm_sra_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sll_epi64() { - let a = _mm_set_epi64x(0xFFFFFFFF, -0xFFFFFFFF); - let r = _mm_sll_epi64(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_set_epi64x(0xFFFFFFFF0, -0xFFFFFFFF0)); - let r = _mm_sll_epi64(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_sll_epi64(a, _mm_set_epi64x(0, 64)); - assert_eq_m128i(r, _mm_set1_epi64x(0)); - let r = _mm_sll_epi64(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi64x(0)); - } - test_mm_sll_epi64(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_srl_epi64() { - let a = _mm_set_epi64x(0xFFFFFFFF, -0xFFFFFFFF); - let r = _mm_srl_epi64(a, _mm_set_epi64x(0, 4)); - assert_eq_m128i(r, _mm_set_epi64x(0xFFFFFFF, 0xFFFFFFFF0000000)); - let r = _mm_srl_epi64(a, _mm_set_epi64x(4, 0)); - assert_eq_m128i(r, a); - let r = _mm_srl_epi64(a, _mm_set_epi64x(0, 64)); - assert_eq_m128i(r, _mm_set1_epi64x(0)); - let r = _mm_srl_epi64(a, _mm_set_epi64x(0, i64::MAX)); - assert_eq_m128i(r, _mm_set1_epi64x(0)); - } - test_mm_srl_epi64(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtepi32_ps() { - let a = _mm_setr_epi32(1, 2, 3, 4); - let r = _mm_cvtepi32_ps(a); - assert_eq_m128(r, _mm_setr_ps(1.0, 2.0, 3.0, 4.0)); - } - test_mm_cvtepi32_ps(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtps_epi32() { - let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let r = _mm_cvtps_epi32(a); - assert_eq_m128i(r, _mm_setr_epi32(1, 2, 3, 4)); - } - test_mm_cvtps_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvttps_epi32() { - let a = _mm_setr_ps(-1.1, 2.2, -3.3, 6.6); - let r = _mm_cvttps_epi32(a); - assert_eq_m128i(r, _mm_setr_epi32(-1, 2, -3, 6)); - - let a = _mm_setr_ps(f32::NEG_INFINITY, f32::INFINITY, f32::MIN, f32::MAX); - let r = _mm_cvttps_epi32(a); - assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, i32::MIN, i32::MIN)); - } - test_mm_cvttps_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_packs_epi16() { - let a = _mm_setr_epi16(0x80, -0x81, 0, 0, 0, 0, 0, 0); - let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -0x81, 0x80); - let r = _mm_packs_epi16(a, b); - assert_eq_m128i( - r, - _mm_setr_epi8(0x7F, -0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0x80, 0x7F), - ); - } - test_mm_packs_epi16(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_packus_epi16() { - let a = _mm_setr_epi16(0x100, -1, 0, 0, 0, 0, 0, 0); - let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -1, 0x100); - let r = _mm_packus_epi16(a, b); - assert_eq_m128i(r, _mm_setr_epi8(!0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, !0)); - } - test_mm_packus_epi16(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_packs_epi32() { - let a = _mm_setr_epi32(0x8000, -0x8001, 0, 0); - let b = _mm_setr_epi32(0, 0, -0x8001, 0x8000); - let r = _mm_packs_epi32(a, b); - assert_eq_m128i(r, _mm_setr_epi16(0x7FFF, -0x8000, 0, 0, 0, 0, -0x8000, 0x7FFF)); - } - test_mm_packs_epi32(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_min_sd() { - let a = _mm_setr_pd(1.0, 2.0); - let b = _mm_setr_pd(5.0, 10.0); - let r = _mm_min_sd(a, b); - assert_eq_m128d(r, _mm_setr_pd(1.0, 2.0)); - } - test_mm_min_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_min_pd() { - let a = _mm_setr_pd(-1.0, 5.0); - let b = _mm_setr_pd(-100.0, 20.0); - let r = _mm_min_pd(a, b); - assert_eq_m128d(r, _mm_setr_pd(-100.0, 5.0)); - - // `_mm_min_pd` can **not** be implemented using the `simd_min` rust intrinsic because - // the semantics of `simd_min` are different to those of `_mm_min_pd` regarding handling - // of `-0.0`. - let a = _mm_setr_pd(-0.0, 0.0); - let b = _mm_setr_pd(0.0, 0.0); - let r1: [u8; 16] = transmute(_mm_min_pd(a, b)); - let r2: [u8; 16] = transmute(_mm_min_pd(b, a)); - let a: [u8; 16] = transmute(a); - let b: [u8; 16] = transmute(b); - assert_eq!(r1, b); - assert_eq!(r2, a); - assert_ne!(a, b); // sanity check that -0.0 is actually present - } - test_mm_min_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_max_sd() { - let a = _mm_setr_pd(1.0, 2.0); - let b = _mm_setr_pd(5.0, 10.0); - let r = _mm_max_sd(a, b); - assert_eq_m128d(r, _mm_setr_pd(5.0, 2.0)); - } - test_mm_max_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_max_pd() { - let a = _mm_setr_pd(-1.0, 5.0); - let b = _mm_setr_pd(-100.0, 20.0); - let r = _mm_max_pd(a, b); - assert_eq_m128d(r, _mm_setr_pd(-1.0, 20.0)); - - // `_mm_max_pd` can **not** be implemented using the `simd_max` rust intrinsic because - // the semantics of `simd_max` are different to those of `_mm_max_pd` regarding handling - // of `-0.0`. - let a = _mm_setr_pd(-0.0, 0.0); - let b = _mm_setr_pd(0.0, 0.0); - let r1: [u8; 16] = transmute(_mm_max_pd(a, b)); - let r2: [u8; 16] = transmute(_mm_max_pd(b, a)); - let a: [u8; 16] = transmute(a); - let b: [u8; 16] = transmute(b); - assert_eq!(r1, b); - assert_eq!(r2, a); - assert_ne!(a, b); // sanity check that -0.0 is actually present - } - test_mm_max_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sqrt_sd() { - let a = _mm_setr_pd(1.0, 2.0); - let b = _mm_setr_pd(5.0, 10.0); - let r = _mm_sqrt_sd(a, b); - assert_eq_m128d(r, _mm_setr_pd(5.0f64.sqrt(), 2.0)); - } - test_mm_sqrt_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_sqrt_pd() { - let r = _mm_sqrt_pd(_mm_setr_pd(1.0, 2.0)); - assert_eq_m128d(r, _mm_setr_pd(1.0f64.sqrt(), 2.0f64.sqrt())); - } - test_mm_sqrt_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpeq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpeq_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpeq_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmplt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmplt_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmplt_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmple_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmple_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmple_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpgt_sd() { - let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpgt_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpgt_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpge_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpge_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpge_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpord_sd() { - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpord_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpord_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpunord_sd() { - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpunord_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpunord_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpneq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(!0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpneq_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpneq_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnlt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpnlt_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnlt_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnle_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpnle_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnle_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpngt_sd() { - let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpngt_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpngt_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnge_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, transmute(2.0f64)); - let r = transmute::<_, __m128i>(_mm_cmpnge_sd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnge_sd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpeq_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, 0); - let r = transmute::<_, __m128i>(_mm_cmpeq_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpeq_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmplt_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, !0); - let r = transmute::<_, __m128i>(_mm_cmplt_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmplt_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmple_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, !0); - let r = transmute::<_, __m128i>(_mm_cmple_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmple_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpgt_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, 0); - let r = transmute::<_, __m128i>(_mm_cmpgt_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpgt_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpge_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(!0, 0); - let r = transmute::<_, __m128i>(_mm_cmpge_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpge_pd(); - - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpord_pd() { - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(0, !0); - let r = transmute::<_, __m128i>(_mm_cmpord_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpord_pd(); + let b = _mm_setr_epi8(0, 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2); + let r = _mm_sad_epu8(a, b); + let e = _mm_setr_epi64x(1020, 614); + assert_eq_m128i(r, e); + } + test_mm_sad_epu8(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sll_epi16() { + let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); + let r = _mm_sll_epi16(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i( + r, + _mm_setr_epi16(0xCC0, -0xCC0, 0xDD0, -0xDD0, 0xEE0, -0xEE0, 0xFF0, -0xFF0), + ); + let r = _mm_sll_epi16(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_sll_epi16(a, _mm_set_epi64x(0, 16)); + assert_eq_m128i(r, _mm_set1_epi16(0)); + let r = _mm_sll_epi16(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi16(0)); + } + test_mm_sll_epi16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_srl_epi16() { + let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); + let r = _mm_srl_epi16(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_setr_epi16(0xC, 0xFF3, 0xD, 0xFF2, 0xE, 0xFF1, 0xF, 0xFF0)); + let r = _mm_srl_epi16(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_srl_epi16(a, _mm_set_epi64x(0, 16)); + assert_eq_m128i(r, _mm_set1_epi16(0)); + let r = _mm_srl_epi16(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi16(0)); + } + test_mm_srl_epi16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sra_epi16() { + let a = _mm_setr_epi16(0xCC, -0xCC, 0xDD, -0xDD, 0xEE, -0xEE, 0xFF, -0xFF); + let r = _mm_sra_epi16(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_setr_epi16(0xC, -0xD, 0xD, -0xE, 0xE, -0xF, 0xF, -0x10)); + let r = _mm_sra_epi16(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_sra_epi16(a, _mm_set_epi64x(0, 16)); + assert_eq_m128i(r, _mm_setr_epi16(0, -1, 0, -1, 0, -1, 0, -1)); + let r = _mm_sra_epi16(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_setr_epi16(0, -1, 0, -1, 0, -1, 0, -1)); + } + test_mm_sra_epi16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sll_epi32() { + let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); + let r = _mm_sll_epi32(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_setr_epi32(0xEEEE0, -0xEEEE0, 0xFFFF0, -0xFFFF0)); + let r = _mm_sll_epi32(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_sll_epi32(a, _mm_set_epi64x(0, 32)); + assert_eq_m128i(r, _mm_set1_epi32(0)); + let r = _mm_sll_epi32(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi32(0)); + } + test_mm_sll_epi32(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_srl_epi32() { + let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); + let r = _mm_srl_epi32(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_setr_epi32(0xEEE, 0xFFFF111, 0xFFF, 0xFFFF000)); + let r = _mm_srl_epi32(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_srl_epi32(a, _mm_set_epi64x(0, 32)); + assert_eq_m128i(r, _mm_set1_epi32(0)); + let r = _mm_srl_epi32(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi32(0)); + } + test_mm_srl_epi32(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sra_epi32() { + let a = _mm_setr_epi32(0xEEEE, -0xEEEE, 0xFFFF, -0xFFFF); + let r = _mm_sra_epi32(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_setr_epi32(0xEEE, -0xEEF, 0xFFF, -0x1000)); + let r = _mm_sra_epi32(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_sra_epi32(a, _mm_set_epi64x(0, 32)); + assert_eq_m128i(r, _mm_setr_epi32(0, -1, 0, -1)); + let r = _mm_sra_epi32(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_setr_epi32(0, -1, 0, -1)); + } + test_mm_sra_epi32(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sll_epi64() { + let a = _mm_set_epi64x(0xFFFFFFFF, -0xFFFFFFFF); + let r = _mm_sll_epi64(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_set_epi64x(0xFFFFFFFF0, -0xFFFFFFFF0)); + let r = _mm_sll_epi64(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_sll_epi64(a, _mm_set_epi64x(0, 64)); + assert_eq_m128i(r, _mm_set1_epi64x(0)); + let r = _mm_sll_epi64(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi64x(0)); + } + test_mm_sll_epi64(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_srl_epi64() { + let a = _mm_set_epi64x(0xFFFFFFFF, -0xFFFFFFFF); + let r = _mm_srl_epi64(a, _mm_set_epi64x(0, 4)); + assert_eq_m128i(r, _mm_set_epi64x(0xFFFFFFF, 0xFFFFFFFF0000000)); + let r = _mm_srl_epi64(a, _mm_set_epi64x(4, 0)); + assert_eq_m128i(r, a); + let r = _mm_srl_epi64(a, _mm_set_epi64x(0, 64)); + assert_eq_m128i(r, _mm_set1_epi64x(0)); + let r = _mm_srl_epi64(a, _mm_set_epi64x(0, i64::MAX)); + assert_eq_m128i(r, _mm_set1_epi64x(0)); + } + test_mm_srl_epi64(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpunord_pd() { - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(!0, 0); - let r = transmute::<_, __m128i>(_mm_cmpunord_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpunord_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtepi32_ps() { + let a = _mm_setr_epi32(1, 2, 3, 4); + let r = _mm_cvtepi32_ps(a); + assert_eq_m128(r, _mm_setr_ps(1.0, 2.0, 3.0, 4.0)); + } + test_mm_cvtepi32_ps(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpneq_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(!0, !0); - let r = transmute::<_, __m128i>(_mm_cmpneq_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpneq_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtps_epi32() { + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let r = _mm_cvtps_epi32(a); + assert_eq_m128i(r, _mm_setr_epi32(1, 2, 3, 4)); + } + test_mm_cvtps_epi32(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnlt_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); - let e = _mm_setr_epi64x(0, 0); - let r = transmute::<_, __m128i>(_mm_cmpnlt_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnlt_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvttps_epi32() { + let a = _mm_setr_ps(-1.1, 2.2, -3.3, 6.6); + let r = _mm_cvttps_epi32(a); + assert_eq_m128i(r, _mm_setr_epi32(-1, 2, -3, 6)); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnle_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, 0); - let r = transmute::<_, __m128i>(_mm_cmpnle_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnle_pd(); + let a = _mm_setr_ps(f32::NEG_INFINITY, f32::INFINITY, f32::MIN, f32::MAX); + let r = _mm_cvttps_epi32(a); + assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, i32::MIN, i32::MIN)); + } + test_mm_cvttps_epi32(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_packs_epi16() { + let a = _mm_setr_epi16(0x80, -0x81, 0, 0, 0, 0, 0, 0); + let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -0x81, 0x80); + let r = _mm_packs_epi16(a, b); + assert_eq_m128i( + r, + _mm_setr_epi8(0x7F, -0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0x80, 0x7F), + ); + } + test_mm_packs_epi16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_packus_epi16() { + let a = _mm_setr_epi16(0x100, -1, 0, 0, 0, 0, 0, 0); + let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -1, 0x100); + let r = _mm_packus_epi16(a, b); + assert_eq_m128i(r, _mm_setr_epi8(!0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, !0)); + } + test_mm_packus_epi16(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_packs_epi32() { + let a = _mm_setr_epi32(0x8000, -0x8001, 0, 0); + let b = _mm_setr_epi32(0, 0, -0x8001, 0x8000); + let r = _mm_packs_epi32(a, b); + assert_eq_m128i(r, _mm_setr_epi16(0x7FFF, -0x8000, 0, 0, 0, 0, -0x8000, 0x7FFF)); + } + test_mm_packs_epi32(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_min_sd() { + let a = _mm_setr_pd(1.0, 2.0); + let b = _mm_setr_pd(5.0, 10.0); + let r = _mm_min_sd(a, b); + assert_eq_m128d(r, _mm_setr_pd(1.0, 2.0)); + } + test_mm_min_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_min_pd() { + let a = _mm_setr_pd(-1.0, 5.0); + let b = _mm_setr_pd(-100.0, 20.0); + let r = _mm_min_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(-100.0, 5.0)); + + // `_mm_min_pd` can **not** be implemented using the `simd_min` rust intrinsic because + // the semantics of `simd_min` are different to those of `_mm_min_pd` regarding handling + // of `-0.0`. + let a = _mm_setr_pd(-0.0, 0.0); + let b = _mm_setr_pd(0.0, 0.0); + let r1: [u8; 16] = transmute(_mm_min_pd(a, b)); + let r2: [u8; 16] = transmute(_mm_min_pd(b, a)); + let a: [u8; 16] = transmute(a); + let b: [u8; 16] = transmute(b); + assert_eq!(r1, b); + assert_eq!(r2, a); + assert_ne!(a, b); // sanity check that -0.0 is actually present + } + test_mm_min_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_max_sd() { + let a = _mm_setr_pd(1.0, 2.0); + let b = _mm_setr_pd(5.0, 10.0); + let r = _mm_max_sd(a, b); + assert_eq_m128d(r, _mm_setr_pd(5.0, 2.0)); + } + test_mm_max_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_max_pd() { + let a = _mm_setr_pd(-1.0, 5.0); + let b = _mm_setr_pd(-100.0, 20.0); + let r = _mm_max_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(-1.0, 20.0)); + + // `_mm_max_pd` can **not** be implemented using the `simd_max` rust intrinsic because + // the semantics of `simd_max` are different to those of `_mm_max_pd` regarding handling + // of `-0.0`. + let a = _mm_setr_pd(-0.0, 0.0); + let b = _mm_setr_pd(0.0, 0.0); + let r1: [u8; 16] = transmute(_mm_max_pd(a, b)); + let r2: [u8; 16] = transmute(_mm_max_pd(b, a)); + let a: [u8; 16] = transmute(a); + let b: [u8; 16] = transmute(b); + assert_eq!(r1, b); + assert_eq!(r2, a); + assert_ne!(a, b); // sanity check that -0.0 is actually present + } + test_mm_max_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sqrt_sd() { + let a = _mm_setr_pd(1.0, 2.0); + let b = _mm_setr_pd(5.0, 10.0); + let r = _mm_sqrt_sd(a, b); + assert_eq_m128d(r, _mm_setr_pd(5.0f64.sqrt(), 2.0)); + } + test_mm_sqrt_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpngt_pd() { - let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, !0); - let r = transmute::<_, __m128i>(_mm_cmpngt_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpngt_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_sqrt_pd() { + let r = _mm_sqrt_pd(_mm_setr_pd(1.0, 2.0)); + assert_eq_m128d(r, _mm_setr_pd(1.0f64.sqrt(), 2.0f64.sqrt())); + } + test_mm_sqrt_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpeq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpeq_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpeq_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmplt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmplt_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmplt_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmple_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmple_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmple_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpgt_sd() { + let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpgt_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpgt_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpge_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpge_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpge_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpord_sd() { + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpord_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpord_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpunord_sd() { + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpunord_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpunord_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpneq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(!0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpneq_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpneq_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnlt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpnlt_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnlt_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnle_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpnle_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnle_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpngt_sd() { + let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpngt_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpngt_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnge_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, transmute(2.0f64)); + let r = transmute::<_, __m128i>(_mm_cmpnge_sd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnge_sd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpeq_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, 0); + let r = transmute::<_, __m128i>(_mm_cmpeq_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpeq_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmplt_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, !0); + let r = transmute::<_, __m128i>(_mm_cmplt_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmplt_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmple_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, !0); + let r = transmute::<_, __m128i>(_mm_cmple_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmple_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpgt_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, 0); + let r = transmute::<_, __m128i>(_mm_cmpgt_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpgt_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpge_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(!0, 0); + let r = transmute::<_, __m128i>(_mm_cmpge_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpge_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpord_pd() { + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(0, !0); + let r = transmute::<_, __m128i>(_mm_cmpord_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpord_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpunord_pd() { + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(!0, 0); + let r = transmute::<_, __m128i>(_mm_cmpunord_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpunord_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpneq_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(!0, !0); + let r = transmute::<_, __m128i>(_mm_cmpneq_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpneq_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnlt_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(5.0, 3.0)); + let e = _mm_setr_epi64x(0, 0); + let r = transmute::<_, __m128i>(_mm_cmpnlt_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnlt_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnle_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, 0); + let r = transmute::<_, __m128i>(_mm_cmpnle_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnle_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpngt_pd() { + let (a, b) = (_mm_setr_pd(5.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, !0); + let r = transmute::<_, __m128i>(_mm_cmpngt_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpngt_pd(); + + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cmpnge_pd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + let e = _mm_setr_epi64x(0, !0); + let r = transmute::<_, __m128i>(_mm_cmpnge_pd(a, b)); + assert_eq_m128i(r, e); + } + test_mm_cmpnge_pd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cmpnge_pd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - let e = _mm_setr_epi64x(0, !0); - let r = transmute::<_, __m128i>(_mm_cmpnge_pd(a, b)); - assert_eq_m128i(r, e); - } - test_mm_cmpnge_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comieq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comieq_sd(a, b) != 0); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comieq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comieq_sd(a, b) != 0); + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comieq_sd(a, b) == 0); + } + test_mm_comieq_sd(); - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comieq_sd(a, b) == 0); - } - test_mm_comieq_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comilt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comilt_sd(a, b) == 0); + } + test_mm_comilt_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comilt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comilt_sd(a, b) == 0); - } - test_mm_comilt_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comile_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comile_sd(a, b) != 0); + } + test_mm_comile_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comile_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comile_sd(a, b) != 0); - } - test_mm_comile_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comigt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comigt_sd(a, b) == 0); + } + test_mm_comigt_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comigt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comigt_sd(a, b) == 0); - } - test_mm_comigt_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comige_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comige_sd(a, b) != 0); + } + test_mm_comige_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comige_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comige_sd(a, b) != 0); - } - test_mm_comige_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_comineq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_comineq_sd(a, b) == 0); + } + test_mm_comineq_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_comineq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_comineq_sd(a, b) == 0); - } - test_mm_comineq_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomieq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomieq_sd(a, b) != 0); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomieq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomieq_sd(a, b) != 0); + let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(NAN, 3.0)); + assert!(_mm_ucomieq_sd(a, b) == 0); + } + test_mm_ucomieq_sd(); - let (a, b) = (_mm_setr_pd(NAN, 2.0), _mm_setr_pd(NAN, 3.0)); - assert!(_mm_ucomieq_sd(a, b) == 0); - } - test_mm_ucomieq_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomilt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomilt_sd(a, b) == 0); + } + test_mm_ucomilt_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomilt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomilt_sd(a, b) == 0); - } - test_mm_ucomilt_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomile_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomile_sd(a, b) != 0); + } + test_mm_ucomile_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomile_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomile_sd(a, b) != 0); - } - test_mm_ucomile_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomigt_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomigt_sd(a, b) == 0); + } + test_mm_ucomigt_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomigt_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomigt_sd(a, b) == 0); - } - test_mm_ucomigt_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomige_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomige_sd(a, b) != 0); + } + test_mm_ucomige_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomige_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomige_sd(a, b) != 0); - } - test_mm_ucomige_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_ucomineq_sd() { + let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); + assert!(_mm_ucomineq_sd(a, b) == 0); + } + test_mm_ucomineq_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_ucomineq_sd() { - let (a, b) = (_mm_setr_pd(1.0, 2.0), _mm_setr_pd(1.0, 3.0)); - assert!(_mm_ucomineq_sd(a, b) == 0); - } - test_mm_ucomineq_sd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtpd_ps() { + let r = _mm_cvtpd_ps(_mm_setr_pd(-1.0, 5.0)); + assert_eq_m128(r, _mm_setr_ps(-1.0, 5.0, 0.0, 0.0)); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtpd_ps() { - let r = _mm_cvtpd_ps(_mm_setr_pd(-1.0, 5.0)); - assert_eq_m128(r, _mm_setr_ps(-1.0, 5.0, 0.0, 0.0)); + let r = _mm_cvtpd_ps(_mm_setr_pd(-1.0, -5.0)); + assert_eq_m128(r, _mm_setr_ps(-1.0, -5.0, 0.0, 0.0)); - let r = _mm_cvtpd_ps(_mm_setr_pd(-1.0, -5.0)); - assert_eq_m128(r, _mm_setr_ps(-1.0, -5.0, 0.0, 0.0)); + let r = _mm_cvtpd_ps(_mm_setr_pd(f64::MAX, f64::MIN)); + assert_eq_m128(r, _mm_setr_ps(f32::INFINITY, f32::NEG_INFINITY, 0.0, 0.0)); - let r = _mm_cvtpd_ps(_mm_setr_pd(f64::MAX, f64::MIN)); - assert_eq_m128(r, _mm_setr_ps(f32::INFINITY, f32::NEG_INFINITY, 0.0, 0.0)); + let r = _mm_cvtpd_ps(_mm_setr_pd(f32::MAX as f64, f32::MIN as f64)); + assert_eq_m128(r, _mm_setr_ps(f32::MAX, f32::MIN, 0.0, 0.0)); + } + test_mm_cvtpd_ps(); - let r = _mm_cvtpd_ps(_mm_setr_pd(f32::MAX as f64, f32::MIN as f64)); - assert_eq_m128(r, _mm_setr_ps(f32::MAX, f32::MIN, 0.0, 0.0)); - } - test_mm_cvtpd_ps(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtps_pd() { + let r = _mm_cvtps_pd(_mm_setr_ps(-1.0, 2.0, -3.0, 5.0)); + assert_eq_m128d(r, _mm_setr_pd(-1.0, 2.0)); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtps_pd() { - let r = _mm_cvtps_pd(_mm_setr_ps(-1.0, 2.0, -3.0, 5.0)); - assert_eq_m128d(r, _mm_setr_pd(-1.0, 2.0)); + let r = _mm_cvtps_pd(_mm_setr_ps(f32::MAX, f32::INFINITY, f32::NEG_INFINITY, f32::MIN)); + assert_eq_m128d(r, _mm_setr_pd(f32::MAX as f64, f64::INFINITY)); + } + test_mm_cvtps_pd(); - let r = _mm_cvtps_pd(_mm_setr_ps(f32::MAX, f32::INFINITY, f32::NEG_INFINITY, f32::MIN)); - assert_eq_m128d(r, _mm_setr_pd(f32::MAX as f64, f64::INFINITY)); - } - test_mm_cvtps_pd(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtpd_epi32() { + let r = _mm_cvtpd_epi32(_mm_setr_pd(-1.0, 5.0)); + assert_eq_m128i(r, _mm_setr_epi32(-1, 5, 0, 0)); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtpd_epi32() { - let r = _mm_cvtpd_epi32(_mm_setr_pd(-1.0, 5.0)); - assert_eq_m128i(r, _mm_setr_epi32(-1, 5, 0, 0)); + let r = _mm_cvtpd_epi32(_mm_setr_pd(-1.0, -5.0)); + assert_eq_m128i(r, _mm_setr_epi32(-1, -5, 0, 0)); - let r = _mm_cvtpd_epi32(_mm_setr_pd(-1.0, -5.0)); - assert_eq_m128i(r, _mm_setr_epi32(-1, -5, 0, 0)); + let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::MAX, f64::MIN)); + assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); - let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::MAX, f64::MIN)); - assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); + let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::INFINITY, f64::NEG_INFINITY)); + assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); - let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::INFINITY, f64::NEG_INFINITY)); - assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); + let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::NAN, f64::NAN)); + assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); + } + test_mm_cvtpd_epi32(); - let r = _mm_cvtpd_epi32(_mm_setr_pd(f64::NAN, f64::NAN)); - assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); - } - test_mm_cvtpd_epi32(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvttpd_epi32() { + let a = _mm_setr_pd(-1.1, 2.2); + let r = _mm_cvttpd_epi32(a); + assert_eq_m128i(r, _mm_setr_epi32(-1, 2, 0, 0)); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvttpd_epi32() { - let a = _mm_setr_pd(-1.1, 2.2); - let r = _mm_cvttpd_epi32(a); - assert_eq_m128i(r, _mm_setr_epi32(-1, 2, 0, 0)); - - let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN); - let r = _mm_cvttpd_epi32(a); - assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); - } - test_mm_cvttpd_epi32(); + let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN); + let r = _mm_cvttpd_epi32(a); + assert_eq_m128i(r, _mm_setr_epi32(i32::MIN, i32::MIN, 0, 0)); + } + test_mm_cvttpd_epi32(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtsd_si32() { - let r = _mm_cvtsd_si32(_mm_setr_pd(-2.0, 5.0)); - assert_eq!(r, -2); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtsd_si32() { + let r = _mm_cvtsd_si32(_mm_setr_pd(-2.0, 5.0)); + assert_eq!(r, -2); - let r = _mm_cvtsd_si32(_mm_setr_pd(f64::MAX, f64::MIN)); - assert_eq!(r, i32::MIN); + let r = _mm_cvtsd_si32(_mm_setr_pd(f64::MAX, f64::MIN)); + assert_eq!(r, i32::MIN); - let r = _mm_cvtsd_si32(_mm_setr_pd(f64::NAN, f64::NAN)); - assert_eq!(r, i32::MIN); - } - test_mm_cvtsd_si32(); + let r = _mm_cvtsd_si32(_mm_setr_pd(f64::NAN, f64::NAN)); + assert_eq!(r, i32::MIN); + } + test_mm_cvtsd_si32(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvttsd_si32() { - let a = _mm_setr_pd(-1.1, 2.2); - let r = _mm_cvttsd_si32(a); - assert_eq!(r, -1); - - let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN); - let r = _mm_cvttsd_si32(a); - assert_eq!(r, i32::MIN); - } - test_mm_cvttsd_si32(); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvttsd_si32() { + let a = _mm_setr_pd(-1.1, 2.2); + let r = _mm_cvttsd_si32(a); + assert_eq!(r, -1); - // Intrinsic only available on x86_64 - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtsd_si64() { - let r = _mm_cvtsd_si64(_mm_setr_pd(-2.0, 5.0)); - assert_eq!(r, -2_i64); + let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN); + let r = _mm_cvttsd_si32(a); + assert_eq!(r, i32::MIN); + } + test_mm_cvttsd_si32(); - let r = _mm_cvtsd_si64(_mm_setr_pd(f64::MAX, f64::MIN)); - assert_eq!(r, i64::MIN); - } - #[cfg(target_arch = "x86_64")] - test_mm_cvtsd_si64(); + // Intrinsic only available on x86_64 + #[cfg(target_arch = "x86_64")] + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtsd_si64() { + let r = _mm_cvtsd_si64(_mm_setr_pd(-2.0, 5.0)); + assert_eq!(r, -2_i64); - // Intrinsic only available on x86_64 - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvttsd_si64() { - let a = _mm_setr_pd(-1.1, 2.2); - let r = _mm_cvttsd_si64(a); - assert_eq!(r, -1_i64); - } - #[cfg(target_arch = "x86_64")] - test_mm_cvttsd_si64(); + let r = _mm_cvtsd_si64(_mm_setr_pd(f64::MAX, f64::MIN)); + assert_eq!(r, i64::MIN); + } + #[cfg(target_arch = "x86_64")] + test_mm_cvtsd_si64(); + + // Intrinsic only available on x86_64 + #[cfg(target_arch = "x86_64")] + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvttsd_si64() { + let a = _mm_setr_pd(-1.1, 2.2); + let r = _mm_cvttsd_si64(a); + assert_eq!(r, -1_i64); + } + #[cfg(target_arch = "x86_64")] + test_mm_cvttsd_si64(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtsd_ss() { - let a = _mm_setr_ps(-1.1, -2.2, 3.3, 4.4); - let b = _mm_setr_pd(2.0, -5.0); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtsd_ss() { + let a = _mm_setr_ps(-1.1, -2.2, 3.3, 4.4); + let b = _mm_setr_pd(2.0, -5.0); - let r = _mm_cvtsd_ss(a, b); + let r = _mm_cvtsd_ss(a, b); - assert_eq_m128(r, _mm_setr_ps(2.0, -2.2, 3.3, 4.4)); + assert_eq_m128(r, _mm_setr_ps(2.0, -2.2, 3.3, 4.4)); - let a = _mm_setr_ps(-1.1, f32::NEG_INFINITY, f32::MAX, f32::NEG_INFINITY); - let b = _mm_setr_pd(f64::INFINITY, -5.0); + let a = _mm_setr_ps(-1.1, f32::NEG_INFINITY, f32::MAX, f32::NEG_INFINITY); + let b = _mm_setr_pd(f64::INFINITY, -5.0); - let r = _mm_cvtsd_ss(a, b); + let r = _mm_cvtsd_ss(a, b); - assert_eq_m128( - r, - _mm_setr_ps(f32::INFINITY, f32::NEG_INFINITY, f32::MAX, f32::NEG_INFINITY), - ); - } - test_mm_cvtsd_ss(); + assert_eq_m128( + r, + _mm_setr_ps(f32::INFINITY, f32::NEG_INFINITY, f32::MAX, f32::NEG_INFINITY), + ); + } + test_mm_cvtsd_ss(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_cvtss_sd() { - let a = _mm_setr_pd(-1.1, 2.2); - let b = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_cvtss_sd() { + let a = _mm_setr_pd(-1.1, 2.2); + let b = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); - let r = _mm_cvtss_sd(a, b); - assert_eq_m128d(r, _mm_setr_pd(1.0, 2.2)); + let r = _mm_cvtss_sd(a, b); + assert_eq_m128d(r, _mm_setr_pd(1.0, 2.2)); - let a = _mm_setr_pd(-1.1, f64::INFINITY); - let b = _mm_setr_ps(f32::NEG_INFINITY, 2.0, 3.0, 4.0); + let a = _mm_setr_pd(-1.1, f64::INFINITY); + let b = _mm_setr_ps(f32::NEG_INFINITY, 2.0, 3.0, 4.0); - let r = _mm_cvtss_sd(a, b); - assert_eq_m128d(r, _mm_setr_pd(f64::NEG_INFINITY, f64::INFINITY)); - } - test_mm_cvtss_sd(); + let r = _mm_cvtss_sd(a, b); + assert_eq_m128d(r, _mm_setr_pd(f64::NEG_INFINITY, f64::INFINITY)); + } + test_mm_cvtss_sd(); - #[target_feature(enable = "sse2")] - unsafe fn test_mm_movemask_pd() { - let r = _mm_movemask_pd(_mm_setr_pd(-1.0, 5.0)); - assert_eq!(r, 0b01); + #[target_feature(enable = "sse2")] + unsafe fn test_mm_movemask_pd() { + let r = _mm_movemask_pd(_mm_setr_pd(-1.0, 5.0)); + assert_eq!(r, 0b01); - let r = _mm_movemask_pd(_mm_setr_pd(-1.0, -5.0)); - assert_eq!(r, 0b11); + let r = _mm_movemask_pd(_mm_setr_pd(-1.0, -5.0)); + assert_eq!(r, 0b11); + } + test_mm_movemask_pd(); } - test_mm_movemask_pd(); } diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs new file mode 100644 index 0000000000000..0805d9bc30039 --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs @@ -0,0 +1,395 @@ +// Ignore everything except x86 and x86_64 +// Any additional target are added to CI should be ignored here +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +// SSSE3 implicitly enables SSE3 +//@compile-flags: -C target-feature=+ssse3 + +use core::mem::transmute; +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +fn main() { + // SSSE3 implicitly enables SSE3, still check it to be sure + assert!(is_x86_feature_detected!("sse3")); + assert!(is_x86_feature_detected!("ssse3")); + + unsafe { + test_sse3(); + test_ssse3(); + } +} + +#[target_feature(enable = "sse3")] +unsafe fn test_sse3() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86/sse3.rs + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_addsub_ps() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_addsub_ps(a, b); + assert_eq_m128(r, _mm_setr_ps(99.0, 25.0, 0.0, -15.0)); + } + test_mm_addsub_ps(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_addsub_pd() { + let a = _mm_setr_pd(-1.0, 5.0); + let b = _mm_setr_pd(-100.0, 20.0); + let r = _mm_addsub_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(99.0, 25.0)); + } + test_mm_addsub_pd(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_hadd_ps() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_hadd_ps(a, b); + assert_eq_m128(r, _mm_setr_ps(4.0, -10.0, -80.0, -5.0)); + } + test_mm_hadd_ps(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_hadd_pd() { + let a = _mm_setr_pd(-1.0, 5.0); + let b = _mm_setr_pd(-100.0, 20.0); + let r = _mm_hadd_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(4.0, -80.0)); + } + test_mm_hadd_pd(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_hsub_ps() { + let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0); + let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0); + let r = _mm_hsub_ps(a, b); + assert_eq_m128(r, _mm_setr_ps(-6.0, 10.0, -120.0, 5.0)); + } + test_mm_hsub_ps(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_hsub_pd() { + let a = _mm_setr_pd(-1.0, 5.0); + let b = _mm_setr_pd(-100.0, 20.0); + let r = _mm_hsub_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(-6.0, -120.0)); + } + test_mm_hsub_pd(); + + #[target_feature(enable = "sse3")] + unsafe fn test_mm_lddqu_si128() { + let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm_lddqu_si128(&a); + assert_eq_m128i(a, r); + } + test_mm_lddqu_si128(); +} + +#[target_feature(enable = "ssse3")] +unsafe fn test_ssse3() { + // Mostly copied from library/stdarch/crates/core_arch/src/x86/ssse3.rs + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_abs_epi8() { + let r = _mm_abs_epi8(_mm_set1_epi8(-5)); + assert_eq_m128i(r, _mm_set1_epi8(5)); + } + test_mm_abs_epi8(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_abs_epi16() { + let r = _mm_abs_epi16(_mm_set1_epi16(-5)); + assert_eq_m128i(r, _mm_set1_epi16(5)); + } + test_mm_abs_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_abs_epi32() { + let r = _mm_abs_epi32(_mm_set1_epi32(-5)); + assert_eq_m128i(r, _mm_set1_epi32(5)); + } + test_mm_abs_epi32(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_shuffle_epi8() { + let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b = _mm_setr_epi8(4, 128_u8 as i8, 4, 3, 24, 12, 6, 19, 12, 5, 5, 10, 4, 1, 8, 0); + let expected = _mm_setr_epi8(5, 0, 5, 4, 9, 13, 7, 4, 13, 6, 6, 11, 5, 2, 9, 1); + let r = _mm_shuffle_epi8(a, b); + assert_eq_m128i(r, expected); + + // Test indices greater than 15 wrapping around + let b = _mm_add_epi8(b, _mm_set1_epi8(32)); + let r = _mm_shuffle_epi8(a, b); + assert_eq_m128i(r, expected); + } + test_mm_shuffle_epi8(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hadd_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(4, 128, 4, 3, 24, 12, 6, 19); + let expected = _mm_setr_epi16(3, 7, 11, 15, 132, 7, 36, 25); + let r = _mm_hadd_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test wrapping on overflow + let a = _mm_setr_epi16(i16::MAX, 1, i16::MAX, 2, i16::MAX, 3, i16::MAX, 4); + let b = _mm_setr_epi16(i16::MIN, -1, i16::MIN, -2, i16::MIN, -3, i16::MIN, -4); + let expected = _mm_setr_epi16( + i16::MIN, + i16::MIN + 1, + i16::MIN + 2, + i16::MIN + 3, + i16::MAX, + i16::MAX - 1, + i16::MAX - 2, + i16::MAX - 3, + ); + let r = _mm_hadd_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hadd_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hadds_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(4, 128, 4, 3, 32767, 1, -32768, -1); + let expected = _mm_setr_epi16(3, 7, 11, 15, 132, 7, 32767, -32768); + let r = _mm_hadds_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test saturating on overflow + let a = _mm_setr_epi16(i16::MAX, 1, i16::MAX, 2, i16::MAX, 3, i16::MAX, 4); + let b = _mm_setr_epi16(i16::MIN, -1, i16::MIN, -2, i16::MIN, -3, i16::MIN, -4); + let expected = _mm_setr_epi16( + i16::MAX, + i16::MAX, + i16::MAX, + i16::MAX, + i16::MIN, + i16::MIN, + i16::MIN, + i16::MIN, + ); + let r = _mm_hadds_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hadds_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hadd_epi32() { + let a = _mm_setr_epi32(1, 2, 3, 4); + let b = _mm_setr_epi32(4, 128, 4, 3); + let expected = _mm_setr_epi32(3, 7, 132, 7); + let r = _mm_hadd_epi32(a, b); + assert_eq_m128i(r, expected); + + // Test wrapping on overflow + let a = _mm_setr_epi32(i32::MAX, 1, i32::MAX, 2); + let b = _mm_setr_epi32(i32::MIN, -1, i32::MIN, -2); + let expected = _mm_setr_epi32(i32::MIN, i32::MIN + 1, i32::MAX, i32::MAX - 1); + let r = _mm_hadd_epi32(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hadd_epi32(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hsub_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(4, 128, 4, 3, 24, 12, 6, 19); + let expected = _mm_setr_epi16(-1, -1, -1, -1, -124, 1, 12, -13); + let r = _mm_hsub_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test wrapping on overflow + let a = _mm_setr_epi16(i16::MAX, -1, i16::MAX, -2, i16::MAX, -3, i16::MAX, -4); + let b = _mm_setr_epi16(i16::MIN, 1, i16::MIN, 2, i16::MIN, 3, i16::MIN, 4); + let expected = _mm_setr_epi16( + i16::MIN, + i16::MIN + 1, + i16::MIN + 2, + i16::MIN + 3, + i16::MAX, + i16::MAX - 1, + i16::MAX - 2, + i16::MAX - 3, + ); + let r = _mm_hsub_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hsub_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hsubs_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(4, 128, 4, 3, 32767, -1, -32768, 1); + let expected = _mm_setr_epi16(-1, -1, -1, -1, -124, 1, 32767, -32768); + let r = _mm_hsubs_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test saturating on overflow + let a = _mm_setr_epi16(i16::MAX, -1, i16::MAX, -2, i16::MAX, -3, i16::MAX, -4); + let b = _mm_setr_epi16(i16::MIN, 1, i16::MIN, 2, i16::MIN, 3, i16::MIN, 4); + let expected = _mm_setr_epi16( + i16::MAX, + i16::MAX, + i16::MAX, + i16::MAX, + i16::MIN, + i16::MIN, + i16::MIN, + i16::MIN, + ); + let r = _mm_hsubs_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hsubs_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_hsub_epi32() { + let a = _mm_setr_epi32(1, 2, 3, 4); + let b = _mm_setr_epi32(4, 128, 4, 3); + let expected = _mm_setr_epi32(-1, -1, -124, 1); + let r = _mm_hsub_epi32(a, b); + assert_eq_m128i(r, expected); + + // Test wrapping on overflow + let a = _mm_setr_epi32(i32::MAX, -1, i32::MAX, -2); + let b = _mm_setr_epi32(i32::MIN, 1, i32::MIN, 2); + let expected = _mm_setr_epi32(i32::MIN, i32::MIN + 1, i32::MAX, i32::MAX - 1); + let r = _mm_hsub_epi32(a, b); + assert_eq_m128i(r, expected); + } + test_mm_hsub_epi32(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_maddubs_epi16() { + let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b = _mm_setr_epi8(4, 63, 4, 3, 24, 12, 6, 19, 12, 5, 5, 10, 4, 1, 8, 0); + let expected = _mm_setr_epi16(130, 24, 192, 194, 158, 175, 66, 120); + let r = _mm_maddubs_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test widening and saturation + let a = _mm_setr_epi8( + u8::MAX as i8, + u8::MAX as i8, + u8::MAX as i8, + u8::MAX as i8, + u8::MAX as i8, + u8::MAX as i8, + 100, + 100, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ); + let b = _mm_setr_epi8( + i8::MAX, + i8::MAX, + i8::MAX, + i8::MIN, + i8::MIN, + i8::MIN, + 50, + 15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ); + let expected = _mm_setr_epi16(i16::MAX, -255, i16::MIN, 6500, 0, 0, 0, 0); + let r = _mm_maddubs_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_maddubs_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_mulhrs_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_setr_epi16(4, 128, 4, 3, 32767, -1, -32768, 1); + let expected = _mm_setr_epi16(0, 0, 0, 0, 5, 0, -7, 0); + let r = _mm_mulhrs_epi16(a, b); + assert_eq_m128i(r, expected); + + // Test extreme values + let a = _mm_setr_epi16(i16::MAX, i16::MIN, i16::MIN, 0, 0, 0, 0, 0); + let b = _mm_setr_epi16(i16::MAX, i16::MIN, i16::MAX, 0, 0, 0, 0, 0); + let expected = _mm_setr_epi16(i16::MAX - 1, i16::MIN, -i16::MAX, 0, 0, 0, 0, 0); + let r = _mm_mulhrs_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_mulhrs_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_sign_epi8() { + let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -14, -15, 16); + let b = _mm_setr_epi8(4, 63, -4, 3, 24, 12, -6, -19, 12, 5, -5, 10, 4, 1, -8, 0); + let expected = _mm_setr_epi8(1, 2, -3, 4, 5, 6, -7, -8, 9, 10, -11, 12, 13, -14, 15, 0); + let r = _mm_sign_epi8(a, b); + assert_eq_m128i(r, expected); + } + test_mm_sign_epi8(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_sign_epi16() { + let a = _mm_setr_epi16(1, 2, 3, 4, -5, -6, 7, 8); + let b = _mm_setr_epi16(4, 128, 0, 3, 1, -1, -2, 1); + let expected = _mm_setr_epi16(1, 2, 0, 4, -5, 6, -7, 8); + let r = _mm_sign_epi16(a, b); + assert_eq_m128i(r, expected); + } + test_mm_sign_epi16(); + + #[target_feature(enable = "ssse3")] + unsafe fn test_mm_sign_epi32() { + let a = _mm_setr_epi32(-1, 2, 3, 4); + let b = _mm_setr_epi32(1, -1, 1, 0); + let expected = _mm_setr_epi32(-1, -2, 3, 0); + let r = _mm_sign_epi32(a, b); + assert_eq_m128i(r, expected); + } + test_mm_sign_epi32(); +} + +#[track_caller] +#[target_feature(enable = "sse")] +unsafe fn assert_eq_m128(a: __m128, b: __m128) { + let r = _mm_cmpeq_ps(a, b); + if _mm_movemask_ps(r) != 0b1111 { + panic!("{:?} != {:?}", a, b); + } +} + +#[track_caller] +#[target_feature(enable = "sse2")] +unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) { + if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 { + panic!("{:?} != {:?}", a, b); + } +} + +#[track_caller] +#[target_feature(enable = "sse2")] +pub unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) { + assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b)) +} diff --git a/src/tools/miri/tests/pass/intrinsics-x86.rs b/src/tools/miri/tests/pass/intrinsics-x86.rs index 88cd782e70a46..90bcdba4353f9 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86.rs @@ -1,3 +1,51 @@ +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86 { + #[cfg(target_arch = "x86")] + use core::arch::x86 as arch; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64 as arch; + + fn adc(c_in: u8, a: u32, b: u32) -> (u8, u32) { + let mut sum = 0; + // SAFETY: There are no safety requirements for calling `_addcarry_u32`. + // It's just unsafe for API consistency with other intrinsics. + let c_out = unsafe { arch::_addcarry_u32(c_in, a, b, &mut sum) }; + (c_out, sum) + } + + fn sbb(b_in: u8, a: u32, b: u32) -> (u8, u32) { + let mut sum = 0; + // SAFETY: There are no safety requirements for calling `_subborrow_u32`. + // It's just unsafe for API consistency with other intrinsics. + let b_out = unsafe { arch::_subborrow_u32(b_in, a, b, &mut sum) }; + (b_out, sum) + } + + pub fn main() { + assert_eq!(adc(0, 1, 1), (0, 2)); + assert_eq!(adc(1, 1, 1), (0, 3)); + assert_eq!(adc(2, 1, 1), (0, 3)); // any non-zero carry acts as 1! + assert_eq!(adc(u8::MAX, 1, 1), (0, 3)); + assert_eq!(adc(0, u32::MAX, u32::MAX), (1, u32::MAX - 1)); + assert_eq!(adc(1, u32::MAX, u32::MAX), (1, u32::MAX)); + assert_eq!(adc(2, u32::MAX, u32::MAX), (1, u32::MAX)); + assert_eq!(adc(u8::MAX, u32::MAX, u32::MAX), (1, u32::MAX)); + + assert_eq!(sbb(0, 1, 1), (0, 0)); + assert_eq!(sbb(1, 1, 1), (1, u32::MAX)); + assert_eq!(sbb(2, 1, 1), (1, u32::MAX)); // any non-zero borrow acts as 1! + assert_eq!(sbb(u8::MAX, 1, 1), (1, u32::MAX)); + assert_eq!(sbb(0, 2, 1), (0, 1)); + assert_eq!(sbb(1, 2, 1), (0, 0)); + assert_eq!(sbb(2, 2, 1), (0, 0)); + assert_eq!(sbb(u8::MAX, 2, 1), (0, 0)); + assert_eq!(sbb(0, 1, 2), (1, u32::MAX)); + assert_eq!(sbb(1, 1, 2), (1, u32::MAX - 1)); + assert_eq!(sbb(2, 1, 2), (1, u32::MAX - 1)); + assert_eq!(sbb(u8::MAX, 1, 2), (1, u32::MAX - 1)); + } +} + #[cfg(target_arch = "x86_64")] mod x86_64 { use core::arch::x86_64 as arch; @@ -10,13 +58,42 @@ mod x86_64 { (c_out, sum) } + fn sbb(b_in: u8, a: u64, b: u64) -> (u8, u64) { + let mut sum = 0; + // SAFETY: There are no safety requirements for calling `_subborrow_u64`. + // It's just unsafe for API consistency with other intrinsics. + let b_out = unsafe { arch::_subborrow_u64(b_in, a, b, &mut sum) }; + (b_out, sum) + } + pub fn main() { + assert_eq!(adc(0, 1, 1), (0, 2)); assert_eq!(adc(1, 1, 1), (0, 3)); - assert_eq!(adc(3, u64::MAX, u64::MAX), (2, 1)); + assert_eq!(adc(2, 1, 1), (0, 3)); // any non-zero carry acts as 1! + assert_eq!(adc(u8::MAX, 1, 1), (0, 3)); + assert_eq!(adc(0, u64::MAX, u64::MAX), (1, u64::MAX - 1)); + assert_eq!(adc(1, u64::MAX, u64::MAX), (1, u64::MAX)); + assert_eq!(adc(2, u64::MAX, u64::MAX), (1, u64::MAX)); + assert_eq!(adc(u8::MAX, u64::MAX, u64::MAX), (1, u64::MAX)); + + assert_eq!(sbb(0, 1, 1), (0, 0)); + assert_eq!(sbb(1, 1, 1), (1, u64::MAX)); + assert_eq!(sbb(2, 1, 1), (1, u64::MAX)); // any non-zero borrow acts as 1! + assert_eq!(sbb(u8::MAX, 1, 1), (1, u64::MAX)); + assert_eq!(sbb(0, 2, 1), (0, 1)); + assert_eq!(sbb(1, 2, 1), (0, 0)); + assert_eq!(sbb(2, 2, 1), (0, 0)); + assert_eq!(sbb(u8::MAX, 2, 1), (0, 0)); + assert_eq!(sbb(0, 1, 2), (1, u64::MAX)); + assert_eq!(sbb(1, 1, 2), (1, u64::MAX - 1)); + assert_eq!(sbb(2, 1, 2), (1, u64::MAX - 1)); + assert_eq!(sbb(u8::MAX, 1, 2), (1, u64::MAX - 1)); } } fn main() { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + x86::main(); #[cfg(target_arch = "x86_64")] x86_64::main(); } diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index ee67a65a4f9a2..969162e2c1e9e 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -1,5 +1,6 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(portable_simd, platform_intrinsics)] +#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)] +#![allow(incomplete_features)] use std::simd::*; extern "platform-intrinsic" { @@ -390,6 +391,8 @@ fn simd_intrinsics() { fn simd_reduce_any(x: T) -> bool; fn simd_reduce_all(x: T) -> bool; fn simd_select(m: M, yes: T, no: T) -> T; + fn simd_shuffle_generic(x: T, y: T) -> U; + fn simd_shuffle(x: T, y: T, idx: IDX) -> U; } unsafe { // Make sure simd_eq returns all-1 for `true` @@ -413,6 +416,16 @@ fn simd_intrinsics() { simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]) ); + assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); + assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3, 1, 0, 2] }), a,); + assert_eq!( + simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b), + i32x4::from_array([4, 2, 1, 10]), + ); + assert_eq!( + simd_shuffle::<_, _, i32x4>(a, b, const { [7, 5, 4, 6] }), + i32x4::from_array([4, 2, 1, 10]), + ); } } diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr index f464e0b4f4948..57caa09c88836 100644 --- a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr @@ -1,12 +1,12 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr index 265f6dfc9c834..69b8a17dc5e12 100644 --- a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.stderr @@ -1,36 +1,36 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └─┬── -| Res| └─┬── -| Res| └──── Strongly protected +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └─┬── +| Rs | └─┬── +| Rs | └──── Strongly protected ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Res| │ └──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| Rs | │ └──── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Dis| ├─┬── -| Dis| │ └─┬── -| Dis| │ └──── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Dis | ├─┬── +| Dis | │ └─┬── +| Dis | │ └──── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr index 673dae6210d88..235ab68fe0178 100644 --- a/src/tools/miri/tests/pass/tree_borrows/formatting.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/formatting.stderr @@ -1,31 +1,31 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1.. 2.. 10.. 11..100..101..1000..1001..1024 -| Act| Act| Act| Act| Act| Act| Act| Act| Act| └─┬── -| Res| Act| Res| Act| Res| Act| Res| Act| Res| └─┬── -|----| Act|----|?Dis|----|?Dis| ----| ?Dis| ----| ├──── -|----|----|----| Act|----|?Dis| ----| ?Dis| ----| ├──── -|----|----|----|----|----| Frz| ----| ?Dis| ----| ├──── -|----|----|----|----|----|----| ----| Act| ----| └──── +0.. 1.. 2.. 10.. 11.. 100.. 101..1000..1001..1024 +| Act | Act | Act | Act | Act | Act | Act | Act | Act | └─┬── +| Rs | Act | Rs | Act | Rs | Act | Rs | Act | Rs | └─┬── +|-----| Act |-----|?Dis |-----|?Dis |-----|?Dis |-----| ├──── +|-----|-----|-----| Act |-----|?Dis |-----|?Dis |-----| ├──── +|-----|-----|-----|-----|-----| Frz |-----|?Dis |-----| ├──── +|-----|-----|-----|-----|-----|-----|-----| Act |-----| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Frz| └─┬── -| Frz| ├─┬── -| Frz| │ ├──── -| Frz| │ └──── -| Frz| ├─┬── -| Frz| │ └─┬── -| Frz| │ └─┬── -| Frz| │ └─┬── -| Frz| │ └──── -| Frz| └─┬── -| Frz| ├─┬── -| Frz| │ ├──── -| Frz| │ └──── -| Frz| └─┬── -| Frz| ├──── -| Frz| └──── +0.. 1 +| Act | └─┬── +| Frz | └─┬── +| Frz | ├─┬── +| Frz | │ ├──── +| Frz | │ └──── +| Frz | ├─┬── +| Frz | │ └─┬── +| Frz | │ └─┬── +| Frz | │ └─┬── +| Frz | │ └──── +| Frz | └─┬── +| Frz | ├─┬── +| Frz | │ ├──── +| Frz | │ └──── +| Frz | └─┬── +| Frz | ├──── +| Frz | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs new file mode 100644 index 0000000000000..d9897a1033fbe --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.rs @@ -0,0 +1,114 @@ +//@compile-flags: -Zmiri-tree-borrows +// This test relies on a specific interleaving that cannot be enforced +// with just barriers. We must remove preemption so that the execution and the +// error messages are deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +use std::ptr::addr_of_mut; +use std::sync::{Arc, Barrier}; +use std::thread; + +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); + +unsafe impl Send for SendPtr {} + +// This test features the problematic pattern +// +// read x || retag y (&mut, protect) +// -- sync -- +// || write y +// +// In which +// - one interleaving (`1:read; 2:retag; 2:write`) does not have UB if retags +// count only as reads for the data race model, +// - the other interleaving (`2:retag; 1:read; 2:write`) has UB (`noalias` violation). +// +// The interleaving executed here is the one that does not have UB, +// i.e. +// 1:read x +// 2:retag y +// 2:write y +// +// Tree Borrows considers that the read of `x` cannot be in conflict +// with `y` because `y` did not even exist yet when `x` was accessed. +// +// As long as we are not emitting any writes for the data race model +// upon retags of mutable references, it should not have any issue with +// this code either. +// We do not want to emit a write for the data race model, because +// although there is race-like behavior going on in this pattern +// (where some but not all interleavings contain UB), making this an actual +// data race has the confusing consequence of one single access being treated +// as being of different `AccessKind`s by different parts of Miri +// (a retag would be always a read for the aliasing model, and sometimes a write +// for the data race model). + +// The other interleaving is a subsequence of `tests/fail/tree_borrows/spurious_read.rs` +// which asserts that +// 2:retag y +// 1:read x +// 2:write y +// is UB. + +type IdxBarrier = (usize, Arc); +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +fn thread_1(x: SendPtr, barrier: IdxBarrier) { + let x = unsafe { &mut *x.0 }; + synchronized!(barrier, "spawn"); + + synchronized!(barrier, "read x || retag y"); + // This is the interleaving without UB: by the time + // the other thread starts retagging, this thread + // has already finished all its work using `y`. + let _v = *x; + synchronized!(barrier, "write y"); + synchronized!(barrier, "exit"); +} + +fn thread_2(y: SendPtr, barrier: IdxBarrier) { + let y = unsafe { &mut *y.0 }; + synchronized!(barrier, "spawn"); + + fn write(y: &mut u8, v: u8, barrier: &IdxBarrier) { + synchronized!(barrier, "write y"); + *y = v; + } + synchronized!(barrier, "read x || retag y"); + // We don't use a barrier here so that *if* the retag counted as a write + // for the data race model, then it would be UB. + // We still want to make sure that the other thread goes first as per the + // interleaving that we are testing, so we use `yield_now + preemption-rate=0` + // which has the effect of forcing a specific interleaving while still + // not counting as "synchronization" from the point of view of the data + // race model. + thread::yield_now(); + write(&mut *y, 42, &barrier); + synchronized!(barrier, "exit"); +} + +fn main() { + let mut data = 0u8; + let p = SendPtr(addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let b1 = (1, Arc::clone(&barrier)); + let b2 = (2, Arc::clone(&barrier)); + + let h1 = thread::spawn(move || thread_1(p, b1)); + let h2 = thread::spawn(move || thread_2(p, b2)); + h1.join().unwrap(); + h2.join().unwrap(); +} diff --git a/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr new file mode 100644 index 0000000000000..f090300851115 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/read_retag_no_race.stderr @@ -0,0 +1,8 @@ +Thread 1 executing: spawn +Thread 2 executing: spawn +Thread 2 executing: read x || retag y +Thread 1 executing: read x || retag y +Thread 1 executing: write y +Thread 2 executing: write y +Thread 2 executing: exit +Thread 1 executing: exit diff --git a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr index b23d78a71566e..f09aa52f1a10a 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.stderr @@ -1,15 +1,15 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Frz| ├──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Frz | ├──── +| Rs | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr index 691fe8b77444d..0d0d52c717fed 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr @@ -1,58 +1,58 @@ [interior mut + protected] Foreign Read: Re* -> Frz ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├─┬── -| Re*| │ └─┬── -| Frz| │ └──── -| Re*| └──── +0.. 1 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├─┬── +| RsM | │ └─┬── +| RsCM| │ └──── +| RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Read: Re* -> Re* ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 8 -| Act| └─┬── -| Re*| └─┬── -| Re*| ├──── -| Re*| └──── +0.. 8 +| Act | └─┬── +| RsM | └─┬── +| RsM | ├──── +| RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Write: Re* -> Re* ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 8 -| Act| └─┬── -| Act| └─┬── -| Re*| ├──── -| Act| └──── +0.. 8 +| Act | └─┬── +| Act | └─┬── +| RsM | ├──── +| Act | └──── ────────────────────────────────────────────────── [protected] Foreign Read: Res -> Frz ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├─┬── -| Res| │ └─┬── -| Frz| │ └──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├─┬── +| Rs | │ └─┬── +| RsC | │ └──── +| Rs | └──── ────────────────────────────────────────────────── [] Foreign Read: Res -> Res ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| ├──── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | ├──── +| Rs | └──── ────────────────────────────────────────────────── [] Foreign Write: Res -> Dis ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Dis| ├──── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Dis | ├──── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs b/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs new file mode 100644 index 0000000000000..71e93d2f84f57 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/spurious_read.rs @@ -0,0 +1,115 @@ +// We ensure a deterministic execution. +// Note that we are *also* using barriers: the barriers enforce the +// specific interleaving of operations that we want, but only the preemption +// rate guarantees that the error message is also deterministic. +//@compile-flags: -Zmiri-preemption-rate=0 +//@compile-flags: -Zmiri-tree-borrows + +use std::sync::{Arc, Barrier}; +use std::thread; + +// A way to send raw pointers across threads. +// Note that when using this in closures will require explicit copying +// `let ptr = ptr;` to force the borrow checker to copy the `Send` wrapper +// instead of just copying the inner `!Send` field. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +fn main() { + retagx_retagy_spuriousx_retx_rety_writey(); +} + +// We're going to enforce a specific interleaving of two +// threads, we use this macro in an effort to make it feasible +// to check in the output that the execution is properly synchronized. +// +// Provide `synchronized!(thread, msg)` where thread is +// a `(thread_id: usize, barrier: Arc)`, and `msg` the message +// to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +// Interleaving: +// retag x (protect) +// retag y (protect) +// spurious read x (target only, which we are executing) +// ret x +// ret y +// write y +// +// This is an interleaving that will never have UB in the source +// (`x` is never accessed for the entire time that `y` is protected). +// For the spurious read to be allowed, we need to check that there is +// no UB in the target (i.e., *with* the spurious read). +// +// The interleaving differs from the one in `tests/fail/tree_borrows/spurious_read.rs` only +// in that it has the `write y` while `y` is no longer protected. +// When the write occurs after protection ends, both source and target are fine +// (checked by this test); when the write occurs during protection, both source +// and target are UB (checked by the `fail` test). +fn retagx_retagy_spuriousx_retx_rety_writey() { + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // This thread only needs to + // - retag `x` protected + // - do a read through `x` + // - remove `x`'s protector + // Most of the complexity here is synchronization. + let thread_x = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn as_mut(x: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "retag y (&mut, protect)"); + synchronized!(b, "spurious read x"); + let _v = *x; + synchronized!(b, "ret x"); + let x = x as *mut u8; + x + } + let _x = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "write y"); + synchronized!(b, "end"); + }); + + // This thread's job is to + // - retag `y` protected + // - (wait a bit that the other thread performs its spurious read) + // - remove `y`'s protector + // - attempt a write through `y`. + let thread_y = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "retag y (&mut, protect)"); + fn as_mut(y: &mut u8, b: (usize, Arc)) -> *mut u8 { + synchronized!(b, "spurious read x"); + synchronized!(b, "ret x"); + let y = y as *mut u8; + y + } + let y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); + synchronized!(b, "ret y"); + synchronized!(b, "write y"); + unsafe { + *y = 2; + } + synchronized!(b, "end"); + }); + + thread_x.join().unwrap(); + thread_y.join().unwrap(); +} diff --git a/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr b/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr new file mode 100644 index 0000000000000..45191eaf9c42f --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/spurious_read.stderr @@ -0,0 +1,16 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: retag y (&mut, protect) +Thread 2 executing: retag y (&mut, protect) +Thread 2 executing: spurious read x +Thread 1 executing: spurious read x +Thread 1 executing: ret x +Thread 2 executing: ret x +Thread 2 executing: ret y +Thread 1 executing: ret y +Thread 1 executing: write y +Thread 2 executing: write y +Thread 2 executing: end +Thread 1 executing: end diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs index 531543441c253..89752bffe9f9d 100644 --- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs +++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs @@ -12,6 +12,7 @@ fn main() { two_mut_protected_same_alloc(); direct_mut_to_const_raw(); local_addr_of_mut(); + returned_mut_is_usable(); // Stacked Borrows tests read_does_not_invalidate1(); @@ -93,6 +94,24 @@ fn two_mut_protected_same_alloc() { write_second(&mut data.0, &mut data.1); } +// This checks that a reborrowed mutable reference returned from a function +// is actually writeable. +// The fact that this is not obvious is due to the addition of +// implicit reads on function exit that might freeze the return value. +fn returned_mut_is_usable() { + fn reborrow(x: &mut u8) -> &mut u8 { + let y = &mut *x; + // Activate the reference so that it is vulnerable to foreign reads. + *y = *y; + y + // An implicit read through `x` is inserted here. + } + let mut data = 0; + let x = &mut data; + let y = reborrow(x); + *y = 1; +} + // ----- The tests below were taken from Stacked Borrows ---- // Make sure that reading from an `&mut` does, like reborrowing to `&`, diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr index f870d3bdec00c..6e774e5014d41 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.default.stderr @@ -1,21 +1,21 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr index 9ab6b879aa762..26d9ad2ad3838 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/unique.uniq.stderr @@ -1,24 +1,24 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Res| └─┬── -| Res| └─┬── -|----| └──── +0.. 1 +| Act | └─┬── +| Rs | └─┬── +| Rs | └─┬── +|-----| └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └─┬── -| Act| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └─┬── +| Act | └──── ────────────────────────────────────────────────── ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 1 -| Act| └─┬── -| Act| └─┬── -| Act| └─┬── -| Dis| └──── +0.. 1 +| Act | └─┬── +| Act | └─┬── +| Act | └─┬── +| Dis | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr index a7712ae91fba8..f63aa1f683497 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.default.stderr @@ -1,6 +1,6 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 2 -| Act| └─┬── -| Res| └──── +0.. 2 +| Act | └─┬── +| Rs | └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr index e9f1cb3b1ed93..7942e9884f401 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr @@ -1,8 +1,8 @@ ────────────────────────────────────────────────── Warning: this tree is indicative only. Some tags may have been hidden. -0.. 2 -| Act| └─┬── -|----| └─┬── -|----| └─┬── -|----| └──── +0.. 2 +| Act | └─┬── +|-----| └─┬── +|-----| └─┬── +|-----| └──── ────────────────────────────────────────────────── diff --git a/src/tools/miri/triagebot.toml b/src/tools/miri/triagebot.toml index 69f3cd2f8109e..1c520a9c77926 100644 --- a/src/tools/miri/triagebot.toml +++ b/src/tools/miri/triagebot.toml @@ -10,5 +10,6 @@ allow-unauthenticated = [ # Gives us the commands 'ready', 'author', 'blocked' [shortcut] -[no-merges] -exclude_labels = ["rollup", "subtree-sync"] +# disabled until https://github.com/rust-lang/triagebot/pull/1720 lands +#[no-merges] +#exclude_titles = ["Rollup of", "sync from rustc"] diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index f1c3dd6aa9bb0..c212e8aafe176 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -23,3 +23,4 @@ glob = "0.3" tempfile = "3.5" derive_builder = "0.12" clap = { version = "4", features = ["derive"] } +tabled = "0.13" diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 978e2dfa4e864..03a1912f5ce02 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -13,10 +13,11 @@ use crate::exec::{cmd, 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::artifact_size::print_binary_sizes; use crate::utils::io::{copy_directory, move_directory, reset_directory}; use crate::utils::{ - clear_llvm_files, format_env_variables, print_binary_sizes, print_free_disk_space, - retry_action, with_log_group, + clear_llvm_files, format_env_variables, print_free_disk_space, retry_action, with_log_group, + write_timer_to_summary, }; mod bolt; @@ -359,6 +360,10 @@ fn main() -> anyhow::Result<()> { let result = execute_pipeline(&env, &mut timer, build_args); log::info!("Timer results\n{}", timer.format_stats()); + if let Ok(summary_path) = std::env::var("GITHUB_STEP_SUMMARY") { + write_timer_to_summary(&summary_path, &timer)?; + } + print_free_disk_space()?; result.context("Optimized build pipeline has failed")?; print_binary_sizes(&env)?; diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 31aabca09f39e..8000c9e7fddcf 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -61,7 +61,7 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> { let config_content = format!( r#"profile = "user" -changelog-seen = 2 +change-id = 115898 [build] rustc = "{rustc}" diff --git a/src/tools/opt-dist/src/utils/artifact_size.rs b/src/tools/opt-dist/src/utils/artifact_size.rs new file mode 100644 index 0000000000000..4dc8952b60a44 --- /dev/null +++ b/src/tools/opt-dist/src/utils/artifact_size.rs @@ -0,0 +1,61 @@ +use std::io::Write; + +use tabled::builder::Builder; +use tabled::settings::object::Columns; +use tabled::settings::style::{BorderChar, Offset}; +use tabled::settings::{Modify, Style}; + +use crate::environment::Environment; +use crate::utils::io::get_files_from_dir; + +pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> { + use humansize::format_size; + use humansize::BINARY; + use std::fmt::Write; + + let root = env.build_artifacts().join("stage2"); + + let mut files = get_files_from_dir(&root.join("bin"), None)?; + files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?); + files.sort_unstable(); + + let items: Vec<_> = files + .into_iter() + .map(|file| { + let size = std::fs::metadata(file.as_std_path()).map(|m| m.len()).unwrap_or(0); + let size_formatted = format_size(size, BINARY); + let name = file.file_name().unwrap().to_string(); + (name, size_formatted) + }) + .collect(); + + // Write to log + let mut output = String::new(); + for (name, size_formatted) in items.iter() { + let name = format!("{}:", name); + writeln!(output, "{name:<50}{size_formatted:>10}")?; + } + log::info!("Rustc artifact size\n{output}"); + + // Write to GitHub summary + if let Ok(summary_path) = std::env::var("GITHUB_STEP_SUMMARY") { + let mut builder = Builder::default(); + for (name, size_formatted) in items { + builder.push_record(vec![name, size_formatted]); + } + + builder.set_header(vec!["Artifact", "Size"]); + let mut table = builder.build(); + + let mut file = std::fs::File::options().append(true).create(true).open(summary_path)?; + writeln!( + file, + "# Artifact size\n{}\n", + table.with(Style::markdown()).with( + Modify::new(Columns::single(1)).with(BorderChar::horizontal(':', Offset::End(0))), + ) + )?; + } + + Ok(()) +} diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs index 6fc96592a8858..ca1292dd5b86a 100644 --- a/src/tools/opt-dist/src/utils/mod.rs +++ b/src/tools/opt-dist/src/utils/mod.rs @@ -1,10 +1,13 @@ -pub mod io; +use sysinfo::{DiskExt, RefreshKind, System, SystemExt}; use crate::environment::Environment; -use crate::utils::io::{delete_directory, get_files_from_dir}; -use humansize::{format_size, BINARY}; +use crate::timer::Timer; +use crate::utils::io::delete_directory; +use humansize::BINARY; use std::time::Duration; -use sysinfo::{DiskExt, RefreshKind, System, SystemExt}; + +pub mod artifact_size; +pub mod io; pub fn format_env_variables() -> String { let vars = std::env::vars().map(|(key, value)| format!("{key}={value}")).collect::>(); @@ -26,28 +29,6 @@ pub fn print_free_disk_space() -> anyhow::Result<()> { Ok(()) } -pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> { - use std::fmt::Write; - - let root = env.build_artifacts().join("stage2"); - - let mut files = get_files_from_dir(&root.join("bin"), None)?; - files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?); - files.sort_unstable(); - - let mut output = String::new(); - for file in files { - let size = std::fs::metadata(file.as_std_path())?.len(); - let size_formatted = format_size(size, BINARY); - let name = format!("{}:", file.file_name().unwrap()); - writeln!(output, "{name:<50}{size_formatted:>10}")?; - } - - log::info!("Rustc artifact size\n{output}"); - - Ok(()) -} - pub fn clear_llvm_files(env: &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 @@ -58,6 +39,24 @@ pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> { Ok(()) } +/// Write the formatted statistics of the timer to a Github Actions summary. +pub fn write_timer_to_summary(path: &str, timer: &Timer) -> anyhow::Result<()> { + use std::io::Write; + + let mut file = std::fs::File::options().append(true).create(true).open(path)?; + writeln!( + file, + r#"# Step durations + +``` +{} +``` +"#, + timer.format_stats() + )?; + Ok(()) +} + /// Wraps all output produced within the `func` closure in a CI output group, if we're running in /// CI. pub fn with_log_group R, R>(group: &str, func: F) -> R { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index d5bc38303e004..002cffa9b0c0f 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2599,7 +2599,8 @@ fn rewrite_fn_base( if where_clause_str.is_empty() { if let ast::FnRetTy::Default(ret_span) = fd.output { match recover_missing_comment_in_span( - mk_sp(params_span.hi(), ret_span.hi()), + // from after the closing paren to right before block or semicolon + mk_sp(ret_span.lo(), span.hi()), shape, context, last_line_width(&result), diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 843ffe2c4c332..f89faacc2d17b 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -18,6 +18,7 @@ const LICENSES: &[&str] = &[ "Apache-2.0/MIT", "ISC", "MIT / Apache-2.0", + "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros "MIT OR Apache-2.0", "MIT OR Zlib OR Apache-2.0", // miniz_oxide @@ -46,6 +47,7 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("mdbook", "MPL-2.0"), // mdbook ("openssl", "Apache-2.0"), // opt-dist + ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`) ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), // rustc (license is the same as LLVM uses) ("ryu", "Apache-2.0 OR BSL-1.0"), // cargo/... (because of serde) ("self_cell", "Apache-2.0"), // rustc (fluent translations) @@ -57,14 +59,14 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[ // tidy-alphabetical-start ("bitmaps", "MPL-2.0+"), ("bytesize", "Apache-2.0"), + ("byteyarn", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"), + ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), ("im-rc", "MPL-2.0+"), - ("imara-diff", "Apache-2.0"), - ("instant", "BSD-3-Clause"), ("normalize-line-endings", "Apache-2.0"), ("openssl", "Apache-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), @@ -179,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "instant", "intl-memoizer", "intl_pluralrules", - "io-lifetimes", "is-terminal", "itertools", "itoa", @@ -217,6 +218,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "pulldown-cmark", "punycode", "quote", + "r-efi", + "r-efi-alloc", "rand", "rand_chacha", "rand_core", @@ -323,7 +326,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "ahash", "anyhow", "arbitrary", - "autocfg", "bitflags", "bumpalo", "cfg-if", diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 3a4d9c53d7bc4..5f6b63a67fda7 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -56,6 +56,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "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/io/error.rs", // Repr unpacked needed for UEFI ]; pub fn check(path: &Path, bad: &mut bool) { diff --git a/src/version b/src/version index dc87e8af82f69..7c7053aa2388a 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.74.0 +1.75.0 diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs new file mode 100644 index 0000000000000..65728a1551667 --- /dev/null +++ b/tests/assembly/closure-inherit-target-feature.rs @@ -0,0 +1,58 @@ +// only-x86_64 +// assembly-output: emit-asm +// make sure the feature is not enabled at compile-time +// compile-flags: -C opt-level=3 -C target-feature=-sse4.1 -C llvm-args=-x86-asm-syntax=intel + +#![feature(target_feature_11)] +#![crate_type = "rlib"] + +use std::arch::x86_64::{__m128, _mm_blend_ps}; + +#[no_mangle] +pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { + let f = { + // check that _mm_blend_ps is not being inlined into the closure + // CHECK-LABEL: {{sse41_blend_nofeature.*closure.*:}} + // CHECK-NOT: blendps + // CHECK: {{call .*_mm_blend_ps.*}} + // CHECK-NOT: blendps + // CHECK: ret + #[inline(never)] |x, y| _mm_blend_ps(x, y, 0b0101) + }; + f(x, y) +} + +#[target_feature(enable = "sse4.1")] +pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 { + let f = { + // check that _mm_blend_ps is being inlined into the closure + // CHECK-LABEL: {{sse41_blend_noinline.*closure.*:}} + // CHECK-NOT: _mm_blend_ps + // CHECK: blendps + // CHECK-NOT: _mm_blend_ps + // CHECK: ret + #[inline(never)] |x, y| unsafe { + _mm_blend_ps(x, y, 0b0101) + } + }; + f(x, y) +} + +#[no_mangle] +#[target_feature(enable = "sse4.1")] +pub fn sse41_blend_doinline(x: __m128, y: __m128) -> __m128 { + // check that the closure and _mm_blend_ps are being inlined into the function + // CHECK-LABEL: sse41_blend_doinline: + // CHECK-NOT: {{sse41_blend_doinline.*closure.*}} + // CHECK-NOT: _mm_blend_ps + // CHECK: blendps + // CHECK-NOT: {{sse41_blend_doinline.*closure.*}} + // CHECK-NOT: _mm_blend_ps + // CHECK: ret + let f = { + #[inline] |x, y| unsafe { + _mm_blend_ps(x, y, 0b0101) + } + }; + f(x, y) +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index a7c9e4845c70a..e46b902df0795 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -9,6 +9,7 @@ // [basic] compile-flags: -Z stack-protector=basic // [none] compile-flags: -Z stack-protector=none // compile-flags: -C opt-level=2 -Z merge-functions=disabled +// min-llvm-version: 17.0.2 #![crate_type = "lib"] @@ -371,7 +372,7 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // all: __stack_chk_fail - // strong: __stack_chk_fail + // strong-NOT: __stack_chk_fail // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs index bc26861581401..690505fd72bd9 100644 --- a/tests/codegen/async-fn-debug-awaitee-field.rs +++ b/tests/codegen/async-fn-debug-awaitee-field.rs @@ -5,12 +5,14 @@ // ignore-tidy-linelength // compile-flags: -C debuginfo=2 --edition=2018 -async fn foo() {} +#![crate_type = "lib"] -async fn async_fn_test() { +pub async fn async_fn_test() { foo().await; } +pub async fn foo() {} + // NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]], // MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$", // NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test", @@ -19,7 +21,3 @@ async fn async_fn_test() { // NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]], // MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$", // NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo", - -fn main() { - let _fn = async_fn_test(); -} diff --git a/tests/codegen/debug-fndef-size.rs b/tests/codegen/debug-fndef-size.rs new file mode 100644 index 0000000000000..80eb35fa32a96 --- /dev/null +++ b/tests/codegen/debug-fndef-size.rs @@ -0,0 +1,18 @@ +// Verify that `i32::cmp` FnDef type is declared with size 0 and align 1 in LLVM debuginfo. +// compile-flags: -O -g -Cno-prepopulate-passes +// ignore-msvc the types are mangled differently + +use std::cmp::Ordering; + +fn foo Ordering>(v1: i32, v2: i32, compare: F) -> Ordering { + compare(&v1, &v2) +} + +pub fn main() { + foo(0, 1, i32::cmp); +} + +// CHECK: %compare.dbg.spill = alloca {}, align 1 +// CHECK: call void @llvm.dbg.declare(metadata ptr %compare.dbg.spill, metadata ![[VAR:.*]], metadata !DIExpression()), !dbg !{{.*}} +// CHECK: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 1, dwarfAddressSpace: {{.*}}) +// CHECK: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 1) diff --git a/tests/codegen/issue-97217.rs b/tests/codegen/issue-97217.rs new file mode 100644 index 0000000000000..af7345442fc51 --- /dev/null +++ b/tests/codegen/issue-97217.rs @@ -0,0 +1,22 @@ +// compile-flags: -C opt-level=3 +// ignore-debug: the debug assertions get in the way +// min-llvm-version: 17.0.2 +#![crate_type = "lib"] + +// Regression test for issue 97217 (the following should result in no allocations) + +// CHECK-LABEL: @issue97217 +#[no_mangle] +pub fn issue97217() -> i32 { + // drop_in_place should be inlined and never appear + // CHECK-NOT: drop_in_place + + // __rust_alloc should be optimized out + // CHECK-NOT: __rust_alloc + + let v1 = vec![5, 6, 7]; + let v1_iter = v1.iter(); + let total: i32 = v1_iter.sum(); + println!("{}",total); + total +} diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs index f345c96e6f765..54c50f840c551 100644 --- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs +++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs @@ -15,8 +15,8 @@ pub fn outer_function(x: S, y: S) -> usize { // Check that we do not attempt to load from the spilled arg before it is assigned to // when generating debuginfo. // CHECK-LABEL: @outer_function -// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]" -// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]] +// CHECK: [[spill:%.*]] = alloca %"{closure@{{.*.rs}}:9:23: 9:25}" +// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"{closure@{{.*.rs}}:9:23: 9:25}", ptr [[spill]] // CHECK-NOT: [[load:%.*]] = load ptr, ptr // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]]) // CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]] diff --git a/tests/codegen/macos/i686-macosx-deployment-target.rs b/tests/codegen/macos/i686-macosx-deployment-target.rs index 17258a264a5e6..ba49178dcb6bf 100644 --- a/tests/codegen/macos/i686-macosx-deployment-target.rs +++ b/tests/codegen/macos/i686-macosx-deployment-target.rs @@ -4,7 +4,7 @@ // compile-flags: -O --target=i686-apple-darwin --crate-type=rlib // needs-llvm-components: x86 -// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.14 #![feature(no_core, lang_items)] #![no_core] @@ -20,7 +20,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "i686-apple-macosx10.9.0" +// CHECK: target triple = "i686-apple-macosx10.14.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/tests/codegen/macos/i686-no-macosx-deployment-target.rs b/tests/codegen/macos/i686-no-macosx-deployment-target.rs index 043040a95e364..479fe7968f78f 100644 --- a/tests/codegen/macos/i686-no-macosx-deployment-target.rs +++ b/tests/codegen/macos/i686-no-macosx-deployment-target.rs @@ -20,7 +20,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "i686-apple-macosx10.7.0" +// CHECK: target triple = "i686-apple-macosx10.12.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/tests/codegen/macos/x86_64-macosx-deployment-target.rs b/tests/codegen/macos/x86_64-macosx-deployment-target.rs index 8e673d11d98e9..957c727bb93a4 100644 --- a/tests/codegen/macos/x86_64-macosx-deployment-target.rs +++ b/tests/codegen/macos/x86_64-macosx-deployment-target.rs @@ -4,7 +4,7 @@ // compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib // needs-llvm-components: x86 -// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.14 #![feature(no_core, lang_items)] #![no_core] @@ -20,7 +20,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "x86_64-apple-macosx10.9.0" +// CHECK: target triple = "x86_64-apple-macosx10.14.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs b/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs index 25ae6924de03e..edbc1b66c713d 100644 --- a/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs +++ b/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs @@ -20,7 +20,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "x86_64-apple-macosx10.7.0" +// CHECK: target triple = "x86_64-apple-macosx10.12.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs index a70ef7751b669..e9dd04e1927be 100644 --- a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs +++ b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs @@ -19,8 +19,9 @@ // only-linux // // revisions:ASAN ASAN-FAT-LTO -//[ASAN] compile-flags: -Zsanitizer=address -//[ASAN-FAT-LTO] compile-flags: -Zsanitizer=address -Cprefer-dynamic=false -Clto=fat +// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +//[ASAN] compile-flags: +//[ASAN-FAT-LTO] compile-flags: -Cprefer-dynamic=false -Clto=fat #![crate_type="staticlib"] diff --git a/tests/codegen/sanitizer/memory-track-origins.rs b/tests/codegen/sanitizer/memory-track-origins.rs index 4bd50508d1520..e15a3b2274ee8 100644 --- a/tests/codegen/sanitizer/memory-track-origins.rs +++ b/tests/codegen/sanitizer/memory-track-origins.rs @@ -4,11 +4,12 @@ // needs-sanitizer-memory // revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO // -//[MSAN-0] compile-flags: -Zsanitizer=memory -//[MSAN-1] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1 -//[MSAN-2] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins -//[MSAN-1-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1 -C lto=fat -//[MSAN-2-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins -C lto=fat +// compile-flags: -Zsanitizer=memory -Ctarget-feature=-crt-static +//[MSAN-0] compile-flags: +//[MSAN-1] compile-flags: -Zsanitizer-memory-track-origins=1 +//[MSAN-2] compile-flags: -Zsanitizer-memory-track-origins +//[MSAN-1-LTO] compile-flags: -Zsanitizer-memory-track-origins=1 -C lto=fat +//[MSAN-2-LTO] compile-flags: -Zsanitizer-memory-track-origins -C lto=fat #![crate_type="lib"] diff --git a/tests/codegen/sanitizer/no-sanitize-inlining.rs b/tests/codegen/sanitizer/no-sanitize-inlining.rs index f4af60baefe9d..e371b19eb3664 100644 --- a/tests/codegen/sanitizer/no-sanitize-inlining.rs +++ b/tests/codegen/sanitizer/no-sanitize-inlining.rs @@ -4,8 +4,9 @@ // needs-sanitizer-address // needs-sanitizer-leak // revisions: ASAN LSAN -//[ASAN] compile-flags: -Zsanitizer=address -C opt-level=3 -Z mir-opt-level=4 -//[LSAN] compile-flags: -Zsanitizer=leak -C opt-level=3 -Z mir-opt-level=4 +// compile-flags: -Copt-level=3 -Zmir-opt-level=4 -Ctarget-feature=-crt-static +//[ASAN] compile-flags: -Zsanitizer=address +//[LSAN] compile-flags: -Zsanitizer=leak #![crate_type="lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index 783b568e2792f..d0b6924345372 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -2,7 +2,7 @@ // selectively disable sanitizer instrumentation. // // needs-sanitizer-address -// compile-flags: -Zsanitizer=address +// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static #![crate_type="lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/sanitizer-recover.rs b/tests/codegen/sanitizer/sanitizer-recover.rs index 7b00fcf8e1bd7..59b1fdd6494ac 100644 --- a/tests/codegen/sanitizer/sanitizer-recover.rs +++ b/tests/codegen/sanitizer/sanitizer-recover.rs @@ -6,6 +6,7 @@ // revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO // no-prefer-dynamic // +// compile-flags: -Ctarget-feature=-crt-static //[ASAN] compile-flags: -Zsanitizer=address -Copt-level=0 //[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0 //[MSAN] compile-flags: -Zsanitizer=memory diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs index 3116f9597bcdb..6e7d3d9316a77 100644 --- a/tests/codegen/simd/simd-wide-sum.rs +++ b/tests/codegen/simd/simd-wide-sum.rs @@ -11,14 +11,14 @@ #![feature(portable_simd)] use std::simd::{Simd, SimdUint}; -const N: usize = 8; +const N: usize = 16; #[no_mangle] // CHECK-LABEL: @wider_reduce_simd pub fn wider_reduce_simd(x: Simd) -> u16 { - // CHECK: zext <8 x i8> - // CHECK-SAME: to <8 x i16> - // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // CHECK: zext <16 x i8> + // CHECK-SAME: to <16 x i16> + // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> let x: Simd = x.cast(); x.reduce_sum() } @@ -26,9 +26,9 @@ pub fn wider_reduce_simd(x: Simd) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_loop pub fn wider_reduce_loop(x: Simd) -> u16 { - // CHECK: zext <8 x i8> - // CHECK-SAME: to <8 x i16> - // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // CHECK: zext <16 x i8> + // CHECK-SAME: to <16 x i16> + // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> let mut sum = 0_u16; for i in 0..N { sum += u16::from(x[i]); @@ -39,9 +39,9 @@ pub fn wider_reduce_loop(x: Simd) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_iter pub fn wider_reduce_iter(x: Simd) -> u16 { - // CHECK: zext <8 x i8> - // CHECK-SAME: to <8 x i16> - // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // CHECK: zext <16 x i8> + // CHECK-SAME: to <16 x i16> + // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> x.as_array().iter().copied().map(u16::from).sum() } @@ -52,8 +52,8 @@ pub fn wider_reduce_iter(x: Simd) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_into_iter pub fn wider_reduce_into_iter(x: Simd) -> u16 { - // CHECK: zext <8 x i8> - // CHECK-SAME: to <8 x i16> - // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // FIXME: It would be nice if this was exactly the same as the above tests, + // but at the time of writing this comment, that didn't happen on LLVM main. + // CHECK: call i16 @llvm.vector.reduce.add x.to_array().into_iter().map(u16::from).sum() } diff --git a/tests/codegen/unwind-landingpad-cold.rs b/tests/codegen/unwind-landingpad-cold.rs new file mode 100644 index 0000000000000..3a902a7d71238 --- /dev/null +++ b/tests/codegen/unwind-landingpad-cold.rs @@ -0,0 +1,16 @@ +// compile-flags: -Cno-prepopulate-passes +// needs-unwind +// min-llvm-version: 17.0.2 +#![crate_type = "lib"] + +// This test checks that drop calls in unwind landing pads +// get the `cold` attribute. + +// CHECK-LABEL: @check_cold +// CHECK: {{(call|invoke) void .+}}drop_in_place{{.+}} [[ATTRIBUTES:#[0-9]+]] +// CHECK: attributes [[ATTRIBUTES]] = { cold } +#[no_mangle] +pub fn check_cold(f: fn(), x: Box) { + // this may unwind + f(); +} diff --git a/tests/codegen/unwind-landingpad-inline.rs b/tests/codegen/unwind-landingpad-inline.rs new file mode 100644 index 0000000000000..0774cefdd2d1a --- /dev/null +++ b/tests/codegen/unwind-landingpad-inline.rs @@ -0,0 +1,39 @@ +// min-llvm-version: 17.0.2 +// compile-flags: -Copt-level=3 +// ignore-debug: the debug assertions get in the way +#![crate_type = "lib"] + +// This test checks that we can inline drop_in_place in +// unwind landing pads. + +// Without inlining, the box pointers escape via the call to drop_in_place, +// and LLVM will not optimize out the pointer comparison. +// With inlining, everything should be optimized out. +// See https://github.com/rust-lang/rust/issues/46515 +// CHECK-LABEL: @check_no_escape_in_landingpad +// CHECK: start: +// CHECK-NEXT: __rust_no_alloc_shim_is_unstable +// CHECK-NEXT: __rust_no_alloc_shim_is_unstable +// CHECK-NEXT: ret void +#[no_mangle] +pub fn check_no_escape_in_landingpad(f: fn()) { + let x = &*Box::new(0); + let y = &*Box::new(0); + + if x as *const _ == y as *const _ { + f(); + } +} + +// Without inlining, the compiler can't tell that +// dropping an empty string (in a landing pad) does nothing. +// With inlining, the landing pad should be optimized out. +// See https://github.com/rust-lang/rust/issues/87055 +// CHECK-LABEL: @check_eliminate_noop_drop +// CHECK: call void %g() +// CHECK-NEXT: ret void +#[no_mangle] +pub fn check_eliminate_noop_drop(g: fn()) { + let _var = String::new(); + g(); +} diff --git a/tests/codegen/vecdeque-nonempty-get-no-panic.rs b/tests/codegen/vecdeque-nonempty-get-no-panic.rs new file mode 100644 index 0000000000000..c2877d2d0ca90 --- /dev/null +++ b/tests/codegen/vecdeque-nonempty-get-no-panic.rs @@ -0,0 +1,17 @@ +// Guards against regression for optimization discussed in issue #80836 + +// compile-flags: -O +// ignore-debug: the debug assertions get in the way + +#![crate_type = "lib"] + +use std::collections::VecDeque; + +// CHECK-LABEL: @front +// CHECK: ret void +#[no_mangle] +pub fn front(v: VecDeque) { + if !v.is_empty() { + v.get(0).unwrap(); + } +} diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage-map/status-quo/async.cov-map index 5f28252ef806e..598791537ad6e 100644 --- a/tests/coverage-map/status-quo/async.cov-map +++ b/tests/coverage-map/status-quo/async.cov-map @@ -38,42 +38,40 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 13, 20) to (start + 0, 25) Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 20) +- Code(Zero) at (prev + 15, 1) to (start + 0, 20) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 20) to (start + 0, 25) +- Code(Zero) at (prev + 15, 20) to (start + 0, 25) Function name: async::executor::block_on::> -Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 6e, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 6e, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 3 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 110, 5) to (start + 10, 54) - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) = ((c0 + c1) - c1) - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) = (c0 + c1) -- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26) + = ((c0 + c1) - c1) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) -- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c1) Function name: async::executor::block_on::VTABLE::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 72, 11, 00, 33] @@ -124,20 +122,20 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 30) +- Code(Zero) at (prev + 19, 1) to (start + 0, 30) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 30) to (start + 0, 45) +- Code(Zero) at (prev + 19, 30) to (start + 0, 45) Function name: async::g Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 17] @@ -148,14 +146,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 21, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (69): 0x[01, 01, 00, 0d, 00, 15, 17, 01, 0c, 00, 02, 09, 00, 0a, 01, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 00, 15, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 13 - Code(Zero) at (prev + 21, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17) +- Code(Zero) at (prev + 0, 14) to (start + 0, 17) - Code(Zero) at (prev + 0, 18) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) @@ -176,14 +174,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (44): 0x[01, 01, 00, 08, 00, 1d, 16, 03, 0c, 00, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 00, 1d, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 8 - Code(Zero) at (prev + 29, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) +- Code(Zero) at (prev + 0, 14) to (start + 0, 19) - Code(Zero) at (prev + 0, 20) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) @@ -199,58 +197,46 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 38, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (84): 0x[01, 01, 05, 01, 00, 0d, 00, 1d, 00, 19, 13, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 03, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 07, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 0b, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 0f, 02, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 02, 19, 07, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(3), rhs = Zero -- expression 2 operands: lhs = Counter(7), rhs = Zero -- expression 3 operands: lhs = Counter(6), rhs = Expression(4, Add) -- expression 4 operands: lhs = Counter(7), rhs = Counter(8) +Number of expressions: 2 +- expression 0 operands: lhs = Counter(6), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(7), rhs = Counter(8) Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 38, 19) to (start + 4, 12) - Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) -- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 18) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) - Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33) -- Code(Expression(1, Add)) at (prev + 0, 39) to (start + 0, 42) - = (c3 + Zero) +- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 42) - Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48) - Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17) - Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23) - Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32) -- Code(Expression(2, Add)) at (prev + 0, 36) to (start + 0, 38) - = (c7 + Zero) +- Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38) - Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16) -- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2) +- Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = (c6 + (c7 + c8)) Function name: async::j -Raw bytes (59): 0x[01, 01, 05, 01, 00, 05, 00, 09, 00, 05, 13, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 03, 00, 0e, 00, 1b, 07, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 0b, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 0f, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 05, 07, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(1), rhs = Zero -- expression 2 operands: lhs = Counter(2), rhs = Zero -- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) -- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +Number of expressions: 2 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 49, 1) to (start + 19, 12) - Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10) -- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 27) - = (c0 + Zero) -- Code(Expression(1, Add)) at (prev + 0, 31) to (start + 0, 39) - = (c1 + Zero) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) +- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 39) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(4)) at (prev + 0, 14) to (start + 0, 26) -- Code(Expression(2, Add)) at (prev + 0, 30) to (start + 0, 32) - = (c2 + Zero) +- Code(Counter(2)) at (prev + 0, 30) to (start + 0, 32) - Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16) -- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2) +- Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = (c1 + (c2 + c3)) Function name: async::j::c @@ -285,12 +271,12 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 67, 5) to (start + 0, 23) Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 01, 4b, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 4b, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 75, 1) to (start + 1, 12) +- Code(Zero) at (prev + 75, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) @@ -323,12 +309,12 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 91, 1) to (start + 0, 25) Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 5b, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 91, 25) to (start + 0, 34) +- Code(Zero) at (prev + 91, 25) to (start + 0, 34) Function name: async::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 5d, 01, 08, 02] diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map index fe74dcd88403f..cc7aed9aee3a4 100644 --- a/tests/coverage-map/status-quo/async2.cov-map +++ b/tests/coverage-map/status-quo/async2.cov-map @@ -38,48 +38,44 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 19, 36) to (start + 2, 2) Function name: async2::executor::block_on:: -Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 3 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54) - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) = ((c0 + c1) - c1) - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) = (c0 + c1) -- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26) + = ((c0 + c1) - c1) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) -- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c1) Function name: async2::executor::block_on:: -Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 3 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54) - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) = ((c0 + c1) - c1) - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) = (c0 + c1) -- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26) + = ((c0 + c1) - c1) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) -- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c1) Function name: async2::executor::block_on::VTABLE::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 2b, 11, 00, 33] diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage-map/status-quo/closure.cov-map index 7dbf6ec834da2..522c1e73afe3d 100644 --- a/tests/coverage-map/status-quo/closure.cov-map +++ b/tests/coverage-map/status-quo/closure.cov-map @@ -1,77 +1,36 @@ Function name: closure::main -Raw bytes (170): 0x[01, 01, 17, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 05, 05, 5a, 01, 05, 18, 01, 08, 01, 0f, 0d, 03, 16, 0e, 06, 0a, 07, 10, 05, 13, 0d, 0b, 1a, 0e, 06, 0a, 0f, 10, 05, 0c, 16, 13, 16, 05, 0d, 18, 17, 19, 09, 01, 1e, 1b, 04, 09, 00, 29, 1f, 01, 09, 00, 2d, 23, 01, 09, 00, 24, 27, 05, 09, 00, 24, 2b, 02, 09, 00, 21, 2f, 04, 09, 00, 21, 33, 04, 09, 00, 28, 37, 09, 09, 00, 32, 3b, 04, 09, 00, 33, 3f, 07, 09, 00, 4b, 43, 08, 09, 00, 48, 47, 0a, 09, 00, 47, 4b, 08, 09, 00, 44, 4f, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 5a, 04, 06, 00, 07, 57, 01, 05, 03, 02] +Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 08, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 23 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(0), rhs = Zero -- expression 2 operands: lhs = Counter(0), rhs = Zero -- expression 3 operands: lhs = Counter(0), rhs = Zero -- expression 4 operands: lhs = Counter(0), rhs = Zero -- expression 5 operands: lhs = Counter(0), rhs = Zero -- expression 6 operands: lhs = Counter(0), rhs = Zero -- expression 7 operands: lhs = Counter(0), rhs = Zero -- expression 8 operands: lhs = Counter(0), rhs = Zero -- expression 9 operands: lhs = Counter(0), rhs = Zero -- expression 10 operands: lhs = Counter(0), rhs = Zero -- expression 11 operands: lhs = Counter(0), rhs = Zero -- expression 12 operands: lhs = Counter(0), rhs = Zero -- expression 13 operands: lhs = Counter(0), rhs = Zero -- expression 14 operands: lhs = Counter(0), rhs = Zero -- expression 15 operands: lhs = Counter(0), rhs = Zero -- expression 16 operands: lhs = Counter(0), rhs = Zero -- expression 17 operands: lhs = Counter(0), rhs = Zero -- expression 18 operands: lhs = Counter(0), rhs = Zero -- expression 19 operands: lhs = Counter(0), rhs = Zero -- expression 20 operands: lhs = Counter(0), rhs = Counter(1) -- expression 21 operands: lhs = Counter(1), rhs = Expression(22, Sub) -- expression 22 operands: lhs = Counter(0), rhs = Counter(1) +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 24 - Code(Counter(0)) at (prev + 8, 1) to (start + 15, 13) -- Code(Expression(0, Add)) at (prev + 22, 14) to (start + 6, 10) - = (c0 + Zero) -- Code(Expression(1, Add)) at (prev + 16, 5) to (start + 19, 13) - = (c0 + Zero) -- Code(Expression(2, Add)) at (prev + 26, 14) to (start + 6, 10) - = (c0 + Zero) -- Code(Expression(3, Add)) at (prev + 16, 5) to (start + 12, 22) - = (c0 + Zero) -- Code(Expression(4, Add)) at (prev + 22, 5) to (start + 13, 24) - = (c0 + Zero) -- Code(Expression(5, Add)) at (prev + 25, 9) to (start + 1, 30) - = (c0 + Zero) -- Code(Expression(6, Add)) at (prev + 4, 9) to (start + 0, 41) - = (c0 + Zero) -- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 45) - = (c0 + Zero) -- Code(Expression(8, Add)) at (prev + 1, 9) to (start + 0, 36) - = (c0 + Zero) -- Code(Expression(9, Add)) at (prev + 5, 9) to (start + 0, 36) - = (c0 + Zero) -- Code(Expression(10, Add)) at (prev + 2, 9) to (start + 0, 33) - = (c0 + Zero) -- Code(Expression(11, Add)) at (prev + 4, 9) to (start + 0, 33) - = (c0 + Zero) -- Code(Expression(12, Add)) at (prev + 4, 9) to (start + 0, 40) - = (c0 + Zero) -- Code(Expression(13, Add)) at (prev + 9, 9) to (start + 0, 50) - = (c0 + Zero) -- Code(Expression(14, Add)) at (prev + 4, 9) to (start + 0, 51) - = (c0 + Zero) -- Code(Expression(15, Add)) at (prev + 7, 9) to (start + 0, 75) - = (c0 + Zero) -- Code(Expression(16, Add)) at (prev + 8, 9) to (start + 0, 72) - = (c0 + Zero) -- Code(Expression(17, Add)) at (prev + 10, 9) to (start + 0, 71) - = (c0 + Zero) -- Code(Expression(18, Add)) at (prev + 8, 9) to (start + 0, 68) - = (c0 + Zero) -- Code(Expression(19, Add)) at (prev + 10, 8) to (start + 0, 16) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10) +- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13) +- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10) +- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22) +- Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24) +- Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 45) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 36) +- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 36) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 33) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 33) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 40) +- Code(Counter(0)) at (prev + 9, 9) to (start + 0, 50) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 51) +- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 75) +- Code(Counter(0)) at (prev + 8, 9) to (start + 0, 72) +- Code(Counter(0)) at (prev + 10, 9) to (start + 0, 71) +- Code(Counter(0)) at (prev + 8, 9) to (start + 0, 68) +- Code(Counter(0)) at (prev + 10, 8) to (start + 0, 16) - Code(Counter(1)) at (prev + 0, 17) to (start + 4, 6) -- Code(Expression(22, Sub)) at (prev + 4, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) -- Code(Expression(21, Add)) at (prev + 1, 5) to (start + 3, 2) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 3, 2) = (c1 + (c0 - c1)) Function name: closure::main::{closure#0} @@ -90,46 +49,45 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#10} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 9a, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9a, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 154, 7) to (start + 0, 33) +- Code(Zero) at (prev + 154, 7) to (start + 0, 33) Function name: closure::main::{closure#11} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 9e, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9e, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 158, 7) to (start + 0, 33) +- Code(Zero) at (prev + 158, 7) to (start + 0, 33) Function name: closure::main::{closure#12} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, a6, 01, 01, 00, 17] +Raw bytes (10): 0x[01, 01, 00, 01, 00, a6, 01, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 166, 1) to (start + 0, 23) +- Code(Zero) at (prev + 166, 1) to (start + 0, 23) Function name: closure::main::{closure#13} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, ab, 01, 0d, 02, 0e] +Raw bytes (10): 0x[01, 01, 00, 01, 00, ab, 01, 0d, 02, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 171, 13) to (start + 2, 14) +- Code(Zero) at (prev + 171, 13) to (start + 2, 14) Function name: closure::main::{closure#14} -Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e] +Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 4 +Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Add), rhs = Zero Number of file 0 mappings: 5 - Code(Expression(0, Add)) at (prev + 178, 13) to (start + 0, 21) = (c1 + (c0 - c1)) @@ -137,40 +95,36 @@ Number of file 0 mappings: 5 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) - Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14) - = ((c1 + (c0 - c1)) + Zero) +- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14) + = (c1 + (c0 - c1)) Function name: closure::main::{closure#15} -Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 -- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) -- expression 2 operands: lhs = Counter(0), rhs = Zero -- expression 3 operands: lhs = Counter(0), rhs = Counter(1) -- expression 4 operands: lhs = Expression(0, Add), rhs = Zero +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 186, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) -- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) -- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51) +- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10) - = ((c1 + (c0 - c1)) + Zero) +- Code(Expression(0, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c0 - c1)) Function name: closure::main::{closure#16} -Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e] +Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 4 +Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Add), rhs = Zero Number of file 0 mappings: 5 - Code(Expression(0, Add)) at (prev + 196, 13) to (start + 0, 21) = (c1 + (c0 - c1)) @@ -178,30 +132,27 @@ Number of file 0 mappings: 5 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) - Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14) - = ((c1 + (c0 - c1)) + Zero) +- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14) + = (c1 + (c0 - c1)) Function name: closure::main::{closure#17} -Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 -- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) -- expression 2 operands: lhs = Counter(0), rhs = Zero -- expression 3 operands: lhs = Counter(0), rhs = Counter(1) -- expression 4 operands: lhs = Expression(0, Add), rhs = Zero +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 204, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) -- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37) -- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51) +- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10) - = ((c1 + (c0 - c1)) + Zero) +- Code(Expression(0, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c0 - c1)) Function name: closure::main::{closure#18} Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 18, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] @@ -264,23 +215,23 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#3} (unused) -Raw bytes (25): 0x[01, 01, 00, 04, 01, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 128, 5) to (start + 1, 20) +- Code(Zero) at (prev + 128, 5) to (start + 1, 20) - Code(Zero) at (prev + 1, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) Function name: closure::main::{closure#4} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 88, 01, 35, 00, 43] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 88, 01, 35, 00, 43] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 136, 53) to (start + 0, 67) +- Code(Zero) at (prev + 136, 53) to (start + 0, 67) Function name: closure::main::{closure#5} Raw bytes (10): 0x[01, 01, 00, 01, 01, 8b, 01, 3d, 00, 4f] @@ -299,26 +250,26 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 140, 65) to (start + 0, 87) Function name: closure::main::{closure#7} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 3b, 00, 51] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 8d, 01, 3b, 00, 51] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 141, 59) to (start + 0, 81) +- Code(Zero) at (prev + 141, 59) to (start + 0, 81) Function name: closure::main::{closure#8} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 92, 01, 3b, 00, 55] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 92, 01, 3b, 00, 55] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 146, 59) to (start + 0, 85) +- Code(Zero) at (prev + 146, 59) to (start + 0, 85) Function name: closure::main::{closure#9} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 01, 94, 01, 38, 02, 06] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 94, 01, 38, 02, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 148, 56) to (start + 2, 6) +- Code(Zero) at (prev + 148, 56) to (start + 2, 6) diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage-map/status-quo/closure_bug.cov-map index 4fe2e5ad243dd..90eeb1a6686f3 100644 --- a/tests/coverage-map/status-quo/closure_bug.cov-map +++ b/tests/coverage-map/status-quo/closure_bug.cov-map @@ -1,89 +1,74 @@ Function name: closure_bug::main -Raw bytes (241): 0x[01, 01, 34, 01, 00, 01, 05, 05, ce, 01, 01, 05, cb, 01, 00, 05, ce, 01, 01, 05, cb, 01, 09, 05, ce, 01, 01, 05, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, c3, 01, 00, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, bb, 01, 00, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, bb, 01, 11, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 11, b6, 01, bb, 01, 11, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 11, 01, 06, 01, 03, 0a, 03, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, ce, 01, 00, 17, 00, 18, cb, 01, 02, 09, 00, 0a, 13, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, c6, 01, 00, 17, 00, 18, c3, 01, 02, 09, 00, 0a, 3b, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, be, 01, 00, 17, 00, 18, bb, 01, 02, 09, 00, 0a, 7b, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, b6, 01, 00, 17, 00, 18, b3, 01, 01, 01, 00, 02] +Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 06, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 52 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(0), rhs = Counter(1) -- expression 2 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 3 operands: lhs = Counter(0), rhs = Counter(1) -- expression 4 operands: lhs = Expression(50, Add), rhs = Zero -- expression 5 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 6 operands: lhs = Counter(0), rhs = Counter(1) -- expression 7 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 8 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 9 operands: lhs = Counter(0), rhs = Counter(1) -- expression 10 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 11 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 12 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 13 operands: lhs = Counter(0), rhs = Counter(1) -- expression 14 operands: lhs = Expression(48, Add), rhs = Zero -- expression 15 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 16 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 17 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 18 operands: lhs = Counter(0), rhs = Counter(1) -- expression 19 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 20 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 21 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 22 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 23 operands: lhs = Counter(0), rhs = Counter(1) -- expression 24 operands: lhs = Counter(3), rhs = Expression(47, Sub) -- expression 25 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 26 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 27 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 28 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 29 operands: lhs = Counter(0), rhs = Counter(1) -- expression 30 operands: lhs = Expression(46, Add), rhs = Zero -- expression 31 operands: lhs = Counter(3), rhs = Expression(47, Sub) -- expression 32 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 33 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 34 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 35 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 36 operands: lhs = Counter(0), rhs = Counter(1) -- expression 37 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 38 operands: lhs = Counter(3), rhs = Expression(47, Sub) -- expression 39 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 40 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 41 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 42 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 43 operands: lhs = Counter(0), rhs = Counter(1) -- expression 44 operands: lhs = Counter(4), rhs = Expression(45, Sub) -- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 46 operands: lhs = Counter(3), rhs = Expression(47, Sub) -- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 48 operands: lhs = Counter(2), rhs = Expression(49, Sub) -- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(2) -- expression 50 operands: lhs = Counter(1), rhs = Expression(51, Sub) -- expression 51 operands: lhs = Counter(0), rhs = Counter(1) +Number of expressions: 38 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 3 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 5 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 6 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 7 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 8 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 9 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Expression(35, Add), rhs = Counter(3) +- expression 12 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 13 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 14 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 15 operands: lhs = Counter(3), rhs = Expression(34, Sub) +- expression 16 operands: lhs = Expression(35, Add), rhs = Counter(3) +- expression 17 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 18 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 19 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 20 operands: lhs = Counter(3), rhs = Expression(34, Sub) +- expression 21 operands: lhs = Expression(35, Add), rhs = Counter(3) +- expression 22 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 23 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 24 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 25 operands: lhs = Expression(33, Add), rhs = Counter(4) +- expression 26 operands: lhs = Counter(3), rhs = Expression(34, Sub) +- expression 27 operands: lhs = Expression(35, Add), rhs = Counter(3) +- expression 28 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 29 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 30 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 31 operands: lhs = Counter(4), rhs = Expression(32, Sub) +- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(4) +- expression 33 operands: lhs = Counter(3), rhs = Expression(34, Sub) +- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(3) +- expression 35 operands: lhs = Counter(2), rhs = Expression(36, Sub) +- expression 36 operands: lhs = Expression(37, Add), rhs = Counter(2) +- expression 37 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 17 - Code(Counter(0)) at (prev + 6, 1) to (start + 3, 10) -- Code(Expression(0, Add)) at (prev + 9, 5) to (start + 1, 14) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14) - Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(51, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 24) = (c0 - c1) -- Code(Expression(50, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(37, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c0 - c1)) +- Code(Expression(37, Add)) at (prev + 6, 5) to (start + 1, 14) = (c1 + (c0 - c1)) -- Code(Expression(4, Add)) at (prev + 6, 5) to (start + 1, 14) - = ((c1 + (c0 - c1)) + Zero) - Code(Counter(2)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(49, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(36, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c1 + (c0 - c1)) - c2) -- Code(Expression(48, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(35, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c2 + ((c1 + (c0 - c1)) - c2)) +- Code(Expression(35, Add)) at (prev + 6, 5) to (start + 1, 14) = (c2 + ((c1 + (c0 - c1)) - c2)) -- Code(Expression(14, Add)) at (prev + 6, 5) to (start + 1, 14) - = ((c2 + ((c1 + (c0 - c1)) - c2)) + Zero) - Code(Counter(3)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(47, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(34, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3) -- Code(Expression(46, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(33, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) +- Code(Expression(33, Add)) at (prev + 6, 5) to (start + 1, 14) = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) -- Code(Expression(30, Add)) at (prev + 6, 5) to (start + 1, 14) - = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + Zero) - Code(Counter(4)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(45, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(32, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4) -- Code(Expression(44, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(31, Add)) at (prev + 1, 1) to (start + 0, 2) = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) Function name: closure_bug::main::{closure#0} diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage-map/status-quo/closure_macro.cov-map index ac017eb446818..b02c7e2e4c66b 100644 --- a/tests/coverage-map/status-quo/closure_macro.cov-map +++ b/tests/coverage-map/status-quo/closure_macro.cov-map @@ -7,27 +7,23 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 2 operands: lhs = Counter(1), rhs = Zero -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19) - = ((c0 - c1) + Zero) -- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85) - = (c1 + Zero) -- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11) - = ((c0 - c1) + Zero) -- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: closure_macro::main::{closure#0} diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage-map/status-quo/closure_macro_async.cov-map index c9a142e5aebcd..7f8666948d902 100644 --- a/tests/coverage-map/status-quo/closure_macro_async.cov-map +++ b/tests/coverage-map/status-quo/closure_macro_async.cov-map @@ -15,27 +15,23 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 2 operands: lhs = Counter(1), rhs = Zero -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 33, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19) - = ((c0 - c1) + Zero) -- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85) - = (c1 + Zero) -- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11) - = ((c0 - c1) + Zero) -- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: closure_macro_async::test::{closure#0}::{closure#0} diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map index d82b8389b4d0b..7600d2d96bdfe 100644 --- a/tests/coverage-map/status-quo/conditions.cov-map +++ b/tests/coverage-map/status-quo/conditions.cov-map @@ -1,14 +1,14 @@ Function name: conditions::main -Raw bytes (793): 0x[01, 01, 90, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, bf, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, ba, 04, 0d, bf, 04, 09, 05, 00, 03, 00, 45, 00, 87, 01, 49, 45, 00, 82, 01, 31, 87, 01, 49, 45, 00, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, 7a, 51, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, ab, 01, 55, 4d, 51, a7, 01, 59, ab, 01, 55, 4d, 51, 49, a3, 01, a7, 01, 59, ab, 01, 55, 4d, 51, 61, 00, e7, 01, 65, 61, 00, e2, 01, 2d, e7, 01, 65, 61, 00, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, da, 01, 6d, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, 8f, 02, 71, 69, 6d, 8b, 02, 75, 8f, 02, 71, 69, 6d, 83, 02, 00, 65, 87, 02, 8b, 02, 75, 8f, 02, 71, 69, 6d, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 79, 00, db, 02, 7d, 79, 00, d6, 02, 29, db, 02, 7d, 79, 00, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, ce, 02, 85, 01, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, fb, 03, 89, 01, 81, 01, 85, 01, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ef, 03, 00, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e2, 03, 19, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, a3, 04, 1d, 15, 19, 9f, 04, 21, a3, 04, 1d, 15, 19, 97, 04, a7, 04, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ab, 04, b6, 04, af, 04, b3, 04, 25, 29, 2d, 31, ba, 04, 0d, bf, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, bf, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ba, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, b6, 04, 03, 09, 00, 0f, 4b, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 87, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 82, 01, 02, 0f, 00, 1c, 7e, 01, 0c, 00, 19, 7a, 00, 1d, 00, 2a, 76, 00, 2e, 00, 3c, a7, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, a3, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9f, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e7, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, e2, 01, 03, 11, 00, 1e, de, 01, 01, 10, 00, 1d, da, 01, 00, 21, 00, 2e, d6, 01, 00, 32, 00, 40, 8b, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 87, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, ff, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, ef, 03, 02, 09, 00, 0a, db, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d6, 02, 02, 0f, 00, 1c, d2, 02, 01, 0c, 00, 19, ce, 02, 00, 1d, 00, 2a, ca, 02, 00, 2e, 00, 3c, f7, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, f3, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 97, 04, 05, 09, 00, 0a, 83, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, ea, 03, 02, 0f, 00, 1c, e6, 03, 01, 0c, 00, 19, e2, 03, 00, 1d, 00, 2a, de, 03, 00, 2e, 00, 3c, 9f, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 9b, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 93, 04, 02, 01, 00, 02] +Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, ab, 04, 25, 29, 2d, 31, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 144 +Number of expressions: 142 - expression 0 operands: lhs = Counter(2), rhs = Expression(12, Add) - expression 1 operands: lhs = Expression(13, Add), rhs = Counter(16) - expression 2 operands: lhs = Expression(14, Add), rhs = Counter(15) - expression 3 operands: lhs = Counter(13), rhs = Counter(14) - expression 4 operands: lhs = Counter(1), rhs = Zero -- expression 5 operands: lhs = Expression(143, Add), rhs = Counter(2) +- expression 5 operands: lhs = Expression(141, Add), rhs = Counter(2) - expression 6 operands: lhs = Counter(1), rhs = Zero - expression 7 operands: lhs = Counter(3), rhs = Counter(13) - expression 8 operands: lhs = Expression(9, Sub), rhs = Counter(14) @@ -18,145 +18,143 @@ Number of expressions: 144 - expression 12 operands: lhs = Expression(13, Add), rhs = Counter(16) - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(15) - expression 14 operands: lhs = Counter(13), rhs = Counter(14) -- expression 15 operands: lhs = Expression(142, Sub), rhs = Counter(3) -- expression 16 operands: lhs = Expression(143, Add), rhs = Counter(2) +- expression 15 operands: lhs = Expression(140, Sub), rhs = Counter(3) +- expression 16 operands: lhs = Expression(141, Add), rhs = Counter(2) - expression 17 operands: lhs = Counter(1), rhs = Zero -- expression 18 operands: lhs = Expression(0, Add), rhs = Zero -- expression 19 operands: lhs = Counter(17), rhs = Zero -- expression 20 operands: lhs = Expression(33, Add), rhs = Counter(18) -- expression 21 operands: lhs = Counter(17), rhs = Zero -- expression 22 operands: lhs = Expression(32, Sub), rhs = Counter(12) -- expression 23 operands: lhs = Expression(33, Add), rhs = Counter(18) -- expression 24 operands: lhs = Counter(17), rhs = Zero -- expression 25 operands: lhs = Expression(31, Sub), rhs = Counter(19) -- expression 26 operands: lhs = Expression(32, Sub), rhs = Counter(12) -- expression 27 operands: lhs = Expression(33, Add), rhs = Counter(18) -- expression 28 operands: lhs = Counter(17), rhs = Zero -- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(20) -- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(19) -- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(12) -- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(18) -- expression 33 operands: lhs = Counter(17), rhs = Zero -- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(21) -- expression 35 operands: lhs = Counter(19), rhs = Counter(20) -- expression 36 operands: lhs = Expression(41, Add), rhs = Counter(22) -- expression 37 operands: lhs = Expression(42, Add), rhs = Counter(21) -- expression 38 operands: lhs = Counter(19), rhs = Counter(20) -- expression 39 operands: lhs = Counter(18), rhs = Expression(40, Add) -- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(22) -- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(21) -- expression 42 operands: lhs = Counter(19), rhs = Counter(20) -- expression 43 operands: lhs = Counter(24), rhs = Zero -- expression 44 operands: lhs = Expression(57, Add), rhs = Counter(25) -- expression 45 operands: lhs = Counter(24), rhs = Zero -- expression 46 operands: lhs = Expression(56, Sub), rhs = Counter(11) -- expression 47 operands: lhs = Expression(57, Add), rhs = Counter(25) -- expression 48 operands: lhs = Counter(24), rhs = Zero -- expression 49 operands: lhs = Expression(55, Sub), rhs = Counter(26) -- expression 50 operands: lhs = Expression(56, Sub), rhs = Counter(11) -- expression 51 operands: lhs = Expression(57, Add), rhs = Counter(25) -- expression 52 operands: lhs = Counter(24), rhs = Zero -- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(27) -- expression 54 operands: lhs = Expression(55, Sub), rhs = Counter(26) -- expression 55 operands: lhs = Expression(56, Sub), rhs = Counter(11) -- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(25) -- expression 57 operands: lhs = Counter(24), rhs = Zero -- expression 58 operands: lhs = Expression(67, Add), rhs = Counter(28) -- expression 59 operands: lhs = Counter(26), rhs = Counter(27) -- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(29) -- expression 61 operands: lhs = Expression(67, Add), rhs = Counter(28) -- expression 62 operands: lhs = Counter(26), rhs = Counter(27) -- expression 63 operands: lhs = Expression(64, Add), rhs = Zero -- expression 64 operands: lhs = Counter(25), rhs = Expression(65, Add) -- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(29) -- expression 66 operands: lhs = Expression(67, Add), rhs = Counter(28) -- expression 67 operands: lhs = Counter(26), rhs = Counter(27) -- expression 68 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 69 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 70 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 71 operands: lhs = Counter(32), rhs = Counter(33) -- expression 72 operands: lhs = Counter(30), rhs = Zero -- expression 73 operands: lhs = Expression(86, Add), rhs = Counter(31) -- expression 74 operands: lhs = Counter(30), rhs = Zero -- expression 75 operands: lhs = Expression(85, Sub), rhs = Counter(10) -- expression 76 operands: lhs = Expression(86, Add), rhs = Counter(31) -- expression 77 operands: lhs = Counter(30), rhs = Zero -- expression 78 operands: lhs = Expression(84, Sub), rhs = Counter(32) -- expression 79 operands: lhs = Expression(85, Sub), rhs = Counter(10) -- expression 80 operands: lhs = Expression(86, Add), rhs = Counter(31) -- expression 81 operands: lhs = Counter(30), rhs = Zero -- expression 82 operands: lhs = Expression(83, Sub), rhs = Counter(33) -- expression 83 operands: lhs = Expression(84, Sub), rhs = Counter(32) -- expression 84 operands: lhs = Expression(85, Sub), rhs = Counter(10) -- expression 85 operands: lhs = Expression(86, Add), rhs = Counter(31) -- expression 86 operands: lhs = Counter(30), rhs = Zero -- expression 87 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 88 operands: lhs = Counter(32), rhs = Counter(33) -- expression 89 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 90 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 91 operands: lhs = Counter(32), rhs = Counter(33) -- expression 92 operands: lhs = Counter(4), rhs = Expression(134, Add) -- expression 93 operands: lhs = Expression(135, Add), rhs = Counter(8) -- expression 94 operands: lhs = Expression(136, Add), rhs = Counter(7) -- expression 95 operands: lhs = Counter(5), rhs = Counter(6) -- expression 96 operands: lhs = Expression(123, Add), rhs = Zero -- expression 97 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 98 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 99 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 100 operands: lhs = Counter(32), rhs = Counter(33) -- expression 101 operands: lhs = Expression(123, Add), rhs = Counter(4) -- expression 102 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 103 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 104 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 105 operands: lhs = Counter(32), rhs = Counter(33) -- expression 106 operands: lhs = Expression(122, Sub), rhs = Counter(9) -- expression 107 operands: lhs = Expression(123, Add), rhs = Counter(4) -- expression 108 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 109 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 110 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 111 operands: lhs = Counter(32), rhs = Counter(33) -- expression 112 operands: lhs = Expression(121, Sub), rhs = Counter(5) -- expression 113 operands: lhs = Expression(122, Sub), rhs = Counter(9) -- expression 114 operands: lhs = Expression(123, Add), rhs = Counter(4) -- expression 115 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 116 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 117 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 118 operands: lhs = Counter(32), rhs = Counter(33) -- expression 119 operands: lhs = Expression(120, Sub), rhs = Counter(6) -- expression 120 operands: lhs = Expression(121, Sub), rhs = Counter(5) -- expression 121 operands: lhs = Expression(122, Sub), rhs = Counter(9) -- expression 122 operands: lhs = Expression(123, Add), rhs = Counter(4) -- expression 123 operands: lhs = Counter(31), rhs = Expression(124, Add) -- expression 124 operands: lhs = Expression(125, Add), rhs = Counter(35) -- expression 125 operands: lhs = Expression(126, Add), rhs = Counter(34) -- expression 126 operands: lhs = Counter(32), rhs = Counter(33) -- expression 127 operands: lhs = Expression(136, Add), rhs = Counter(7) -- expression 128 operands: lhs = Counter(5), rhs = Counter(6) -- expression 129 operands: lhs = Expression(135, Add), rhs = Counter(8) -- expression 130 operands: lhs = Expression(136, Add), rhs = Counter(7) -- expression 131 operands: lhs = Counter(5), rhs = Counter(6) -- expression 132 operands: lhs = Expression(133, Add), rhs = Expression(137, Add) -- expression 133 operands: lhs = Counter(4), rhs = Expression(134, Add) -- expression 134 operands: lhs = Expression(135, Add), rhs = Counter(8) -- expression 135 operands: lhs = Expression(136, Add), rhs = Counter(7) -- expression 136 operands: lhs = Counter(5), rhs = Counter(6) -- expression 137 operands: lhs = Expression(138, Add), rhs = Expression(141, Sub) -- expression 138 operands: lhs = Expression(139, Add), rhs = Expression(140, Add) -- expression 139 operands: lhs = Counter(9), rhs = Counter(10) -- expression 140 operands: lhs = Counter(11), rhs = Counter(12) -- expression 141 operands: lhs = Expression(142, Sub), rhs = Counter(3) -- expression 142 operands: lhs = Expression(143, Add), rhs = Counter(2) -- expression 143 operands: lhs = Counter(1), rhs = Zero +- expression 18 operands: lhs = Counter(17), rhs = Zero +- expression 19 operands: lhs = Expression(32, Add), rhs = Counter(18) +- expression 20 operands: lhs = Counter(17), rhs = Zero +- expression 21 operands: lhs = Expression(31, Sub), rhs = Counter(12) +- expression 22 operands: lhs = Expression(32, Add), rhs = Counter(18) +- expression 23 operands: lhs = Counter(17), rhs = Zero +- expression 24 operands: lhs = Expression(30, Sub), rhs = Counter(19) +- expression 25 operands: lhs = Expression(31, Sub), rhs = Counter(12) +- expression 26 operands: lhs = Expression(32, Add), rhs = Counter(18) +- expression 27 operands: lhs = Counter(17), rhs = Zero +- expression 28 operands: lhs = Expression(29, Sub), rhs = Counter(20) +- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(19) +- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(12) +- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(18) +- expression 32 operands: lhs = Counter(17), rhs = Zero +- expression 33 operands: lhs = Expression(41, Add), rhs = Counter(21) +- expression 34 operands: lhs = Counter(19), rhs = Counter(20) +- expression 35 operands: lhs = Expression(40, Add), rhs = Counter(22) +- expression 36 operands: lhs = Expression(41, Add), rhs = Counter(21) +- expression 37 operands: lhs = Counter(19), rhs = Counter(20) +- expression 38 operands: lhs = Counter(18), rhs = Expression(39, Add) +- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(22) +- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(21) +- expression 41 operands: lhs = Counter(19), rhs = Counter(20) +- expression 42 operands: lhs = Counter(24), rhs = Zero +- expression 43 operands: lhs = Expression(56, Add), rhs = Counter(25) +- expression 44 operands: lhs = Counter(24), rhs = Zero +- expression 45 operands: lhs = Expression(55, Sub), rhs = Counter(11) +- expression 46 operands: lhs = Expression(56, Add), rhs = Counter(25) +- expression 47 operands: lhs = Counter(24), rhs = Zero +- expression 48 operands: lhs = Expression(54, Sub), rhs = Counter(26) +- expression 49 operands: lhs = Expression(55, Sub), rhs = Counter(11) +- expression 50 operands: lhs = Expression(56, Add), rhs = Counter(25) +- expression 51 operands: lhs = Counter(24), rhs = Zero +- expression 52 operands: lhs = Expression(53, Sub), rhs = Counter(27) +- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(26) +- expression 54 operands: lhs = Expression(55, Sub), rhs = Counter(11) +- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(25) +- expression 56 operands: lhs = Counter(24), rhs = Zero +- expression 57 operands: lhs = Expression(66, Add), rhs = Counter(28) +- expression 58 operands: lhs = Counter(26), rhs = Counter(27) +- expression 59 operands: lhs = Expression(65, Add), rhs = Counter(29) +- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(28) +- expression 61 operands: lhs = Counter(26), rhs = Counter(27) +- expression 62 operands: lhs = Expression(63, Add), rhs = Zero +- expression 63 operands: lhs = Counter(25), rhs = Expression(64, Add) +- expression 64 operands: lhs = Expression(65, Add), rhs = Counter(29) +- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(28) +- expression 66 operands: lhs = Counter(26), rhs = Counter(27) +- expression 67 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 68 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 69 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 70 operands: lhs = Counter(32), rhs = Counter(33) +- expression 71 operands: lhs = Counter(30), rhs = Zero +- expression 72 operands: lhs = Expression(85, Add), rhs = Counter(31) +- expression 73 operands: lhs = Counter(30), rhs = Zero +- expression 74 operands: lhs = Expression(84, Sub), rhs = Counter(10) +- expression 75 operands: lhs = Expression(85, Add), rhs = Counter(31) +- expression 76 operands: lhs = Counter(30), rhs = Zero +- expression 77 operands: lhs = Expression(83, Sub), rhs = Counter(32) +- expression 78 operands: lhs = Expression(84, Sub), rhs = Counter(10) +- expression 79 operands: lhs = Expression(85, Add), rhs = Counter(31) +- expression 80 operands: lhs = Counter(30), rhs = Zero +- expression 81 operands: lhs = Expression(82, Sub), rhs = Counter(33) +- expression 82 operands: lhs = Expression(83, Sub), rhs = Counter(32) +- expression 83 operands: lhs = Expression(84, Sub), rhs = Counter(10) +- expression 84 operands: lhs = Expression(85, Add), rhs = Counter(31) +- expression 85 operands: lhs = Counter(30), rhs = Zero +- expression 86 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 87 operands: lhs = Counter(32), rhs = Counter(33) +- expression 88 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 89 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 90 operands: lhs = Counter(32), rhs = Counter(33) +- expression 91 operands: lhs = Counter(4), rhs = Expression(132, Add) +- expression 92 operands: lhs = Expression(133, Add), rhs = Counter(8) +- expression 93 operands: lhs = Expression(134, Add), rhs = Counter(7) +- expression 94 operands: lhs = Counter(5), rhs = Counter(6) +- expression 95 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 96 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 97 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 98 operands: lhs = Counter(32), rhs = Counter(33) +- expression 99 operands: lhs = Expression(121, Add), rhs = Counter(4) +- expression 100 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 101 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 102 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 103 operands: lhs = Counter(32), rhs = Counter(33) +- expression 104 operands: lhs = Expression(120, Sub), rhs = Counter(9) +- expression 105 operands: lhs = Expression(121, Add), rhs = Counter(4) +- expression 106 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 107 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 108 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 109 operands: lhs = Counter(32), rhs = Counter(33) +- expression 110 operands: lhs = Expression(119, Sub), rhs = Counter(5) +- expression 111 operands: lhs = Expression(120, Sub), rhs = Counter(9) +- expression 112 operands: lhs = Expression(121, Add), rhs = Counter(4) +- expression 113 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 114 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 115 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 116 operands: lhs = Counter(32), rhs = Counter(33) +- expression 117 operands: lhs = Expression(118, Sub), rhs = Counter(6) +- expression 118 operands: lhs = Expression(119, Sub), rhs = Counter(5) +- expression 119 operands: lhs = Expression(120, Sub), rhs = Counter(9) +- expression 120 operands: lhs = Expression(121, Add), rhs = Counter(4) +- expression 121 operands: lhs = Counter(31), rhs = Expression(122, Add) +- expression 122 operands: lhs = Expression(123, Add), rhs = Counter(35) +- expression 123 operands: lhs = Expression(124, Add), rhs = Counter(34) +- expression 124 operands: lhs = Counter(32), rhs = Counter(33) +- expression 125 operands: lhs = Expression(134, Add), rhs = Counter(7) +- expression 126 operands: lhs = Counter(5), rhs = Counter(6) +- expression 127 operands: lhs = Expression(133, Add), rhs = Counter(8) +- expression 128 operands: lhs = Expression(134, Add), rhs = Counter(7) +- expression 129 operands: lhs = Counter(5), rhs = Counter(6) +- expression 130 operands: lhs = Expression(131, Add), rhs = Expression(135, Add) +- expression 131 operands: lhs = Counter(4), rhs = Expression(132, Add) +- expression 132 operands: lhs = Expression(133, Add), rhs = Counter(8) +- expression 133 operands: lhs = Expression(134, Add), rhs = Counter(7) +- expression 134 operands: lhs = Counter(5), rhs = Counter(6) +- expression 135 operands: lhs = Expression(136, Add), rhs = Expression(139, Sub) +- expression 136 operands: lhs = Expression(137, Add), rhs = Expression(138, Add) +- expression 137 operands: lhs = Counter(9), rhs = Counter(10) +- expression 138 operands: lhs = Counter(11), rhs = Counter(12) +- expression 139 operands: lhs = Expression(140, Sub), rhs = Counter(3) +- expression 140 operands: lhs = Expression(141, Add), rhs = Counter(2) +- expression 141 operands: lhs = Counter(1), rhs = Zero Number of file 0 mappings: 68 - Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) = (c2 + (((c13 + c14) + c15) + c16)) -- Code(Expression(143, Add)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(141, Add)) at (prev + 0, 16) to (start + 0, 29) = (c1 + Zero) - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10) -- Code(Expression(142, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(140, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c1 + Zero) - c2) - Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25) - Code(Expression(9, Sub)) at (prev + 0, 29) to (start + 0, 42) @@ -168,94 +166,94 @@ Number of file 0 mappings: 68 - Code(Counter(16)) at (prev + 2, 10) to (start + 0, 11) - Code(Expression(12, Add)) at (prev + 1, 9) to (start + 1, 18) = (((c13 + c14) + c15) + c16) -- Code(Expression(141, Sub)) at (prev + 3, 9) to (start + 0, 15) +- Code(Expression(139, Sub)) at (prev + 3, 9) to (start + 0, 15) = (((c1 + Zero) - c2) - c3) -- Code(Expression(18, Add)) at (prev + 3, 9) to (start + 1, 12) - = ((c2 + (((c13 + c14) + c15) + c16)) + Zero) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12) + = (c2 + (((c13 + c14) + c15) + c16)) - Code(Counter(17)) at (prev + 1, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(33, Add)) at (prev + 2, 8) to (start + 0, 21) +- Code(Expression(32, Add)) at (prev + 2, 8) to (start + 0, 21) = (c17 + Zero) - Code(Counter(18)) at (prev + 0, 22) to (start + 2, 6) -- Code(Expression(32, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(31, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c17 + Zero) - c18) -- Code(Expression(31, Sub)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(30, Sub)) at (prev + 1, 12) to (start + 0, 25) = (((c17 + Zero) - c18) - c12) -- Code(Expression(30, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(29, Sub)) at (prev + 0, 29) to (start + 0, 42) = ((((c17 + Zero) - c18) - c12) - c19) -- Code(Expression(29, Sub)) at (prev + 0, 46) to (start + 0, 60) +- Code(Expression(28, Sub)) at (prev + 0, 46) to (start + 0, 60) = (((((c17 + Zero) - c18) - c12) - c19) - c20) -- Code(Expression(41, Add)) at (prev + 0, 61) to (start + 2, 10) +- Code(Expression(40, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c19 + c20) + c21) - Code(Counter(22)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(40, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(39, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c19 + c20) + c21) + c22) - Code(Counter(12)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(39, Add)) at (prev + 3, 8) to (start + 0, 12) +- Code(Expression(38, Add)) at (prev + 3, 8) to (start + 0, 12) = (c18 + (((c19 + c20) + c21) + c22)) - Code(Counter(23)) at (prev + 1, 13) to (start + 1, 16) - Code(Counter(24)) at (prev + 1, 17) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(57, Add)) at (prev + 2, 12) to (start + 0, 25) +- Code(Expression(56, Add)) at (prev + 2, 12) to (start + 0, 25) = (c24 + Zero) - Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(56, Sub)) at (prev + 3, 17) to (start + 0, 30) +- Code(Expression(55, Sub)) at (prev + 3, 17) to (start + 0, 30) = ((c24 + Zero) - c25) -- Code(Expression(55, Sub)) at (prev + 1, 16) to (start + 0, 29) +- Code(Expression(54, Sub)) at (prev + 1, 16) to (start + 0, 29) = (((c24 + Zero) - c25) - c11) -- Code(Expression(54, Sub)) at (prev + 0, 33) to (start + 0, 46) +- Code(Expression(53, Sub)) at (prev + 0, 33) to (start + 0, 46) = ((((c24 + Zero) - c25) - c11) - c26) -- Code(Expression(53, Sub)) at (prev + 0, 50) to (start + 0, 64) +- Code(Expression(52, Sub)) at (prev + 0, 50) to (start + 0, 64) = (((((c24 + Zero) - c25) - c11) - c26) - c27) -- Code(Expression(66, Add)) at (prev + 0, 65) to (start + 2, 14) +- Code(Expression(65, Add)) at (prev + 0, 65) to (start + 2, 14) = ((c26 + c27) + c28) - Code(Counter(29)) at (prev + 2, 14) to (start + 0, 15) -- Code(Expression(65, Add)) at (prev + 1, 13) to (start + 0, 27) +- Code(Expression(64, Add)) at (prev + 1, 13) to (start + 0, 27) = (((c26 + c27) + c28) + c29) - Code(Counter(11)) at (prev + 2, 13) to (start + 0, 19) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(63, Add)) at (prev + 2, 9) to (start + 1, 12) +- Code(Expression(62, Add)) at (prev + 2, 9) to (start + 1, 12) = ((c25 + (((c26 + c27) + c28) + c29)) + Zero) - Code(Counter(30)) at (prev + 1, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(123, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(121, Add)) at (prev + 2, 9) to (start + 0, 10) = (c31 + (((c32 + c33) + c34) + c35)) -- Code(Expression(86, Add)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(85, Add)) at (prev + 0, 16) to (start + 0, 29) = (c30 + Zero) - Code(Counter(31)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(85, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(84, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c30 + Zero) - c31) -- Code(Expression(84, Sub)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(83, Sub)) at (prev + 1, 12) to (start + 0, 25) = (((c30 + Zero) - c31) - c10) -- Code(Expression(83, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(82, Sub)) at (prev + 0, 29) to (start + 0, 42) = ((((c30 + Zero) - c31) - c10) - c32) -- Code(Expression(82, Sub)) at (prev + 0, 46) to (start + 0, 60) +- Code(Expression(81, Sub)) at (prev + 0, 46) to (start + 0, 60) = (((((c30 + Zero) - c31) - c10) - c32) - c33) -- Code(Expression(125, Add)) at (prev + 0, 61) to (start + 2, 10) +- Code(Expression(123, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c32 + c33) + c34) - Code(Counter(35)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(124, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(122, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c32 + c33) + c34) + c35) - Code(Counter(10)) at (prev + 2, 13) to (start + 2, 15) -- Code(Expression(133, Add)) at (prev + 5, 9) to (start + 0, 10) +- Code(Expression(131, Add)) at (prev + 5, 9) to (start + 0, 10) = (c4 + (((c5 + c6) + c7) + c8)) -- Code(Expression(96, Add)) at (prev + 0, 16) to (start + 0, 29) - = ((c31 + (((c32 + c33) + c34) + c35)) + Zero) +- Code(Expression(121, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c31 + (((c32 + c33) + c34) + c35)) - Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(122, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(120, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c31 + (((c32 + c33) + c34) + c35)) - c4) -- Code(Expression(121, Sub)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(119, Sub)) at (prev + 1, 12) to (start + 0, 25) = (((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) -- Code(Expression(120, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(118, Sub)) at (prev + 0, 29) to (start + 0, 42) = ((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) -- Code(Expression(119, Sub)) at (prev + 0, 46) to (start + 0, 60) +- Code(Expression(117, Sub)) at (prev + 0, 46) to (start + 0, 60) = (((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) - c6) -- Code(Expression(135, Add)) at (prev + 0, 61) to (start + 2, 10) +- Code(Expression(133, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c5 + c6) + c7) - Code(Counter(8)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(134, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(132, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c5 + c6) + c7) + c8) - Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(132, Add)) at (prev + 2, 1) to (start + 0, 2) +- Code(Expression(130, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c4 + (((c5 + c6) + c7) + c8)) + (((c9 + c10) + (c11 + c12)) + (((c1 + Zero) - c2) - c3))) diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage-map/status-quo/continue.cov-map index c78cf293079ea..82f3d7c609529 100644 --- a/tests/coverage-map/status-quo/continue.cov-map +++ b/tests/coverage-map/status-quo/continue.cov-map @@ -1,8 +1,8 @@ Function name: continue::main -Raw bytes (216): 0x[01, 01, 1f, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 15, 00, 19, 37, 1d, 21, 33, 25, 19, 37, 1d, 21, 1d, 00, 25, 4f, 29, 2d, 4b, 31, 25, 4f, 29, 2d, 31, 67, 35, 39, 5f, 3d, 31, 67, 35, 39, 35, 39, 3d, 41, 73, 45, 3d, 41, 41, 00, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 23, 03, 09, 00, 0e, 33, 02, 0e, 00, 13, 2e, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 3b, 03, 09, 00, 0e, 4b, 02, 0e, 00, 13, 46, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 5f, 03, 0e, 00, 13, 5a, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 67, 04, 09, 00, 0e, 73, 02, 0e, 00, 13, 6e, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 77, 03, 09, 00, 0e, 7b, 02, 0d, 01, 02] +Raw bytes (210): 0x[01, 01, 1c, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 19, 33, 1d, 21, 2f, 25, 19, 33, 1d, 21, 25, 47, 29, 2d, 43, 31, 25, 47, 29, 2d, 31, 5f, 35, 39, 57, 3d, 31, 5f, 35, 39, 35, 39, 3d, 41, 6b, 45, 3d, 41, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 15, 03, 09, 00, 0e, 2f, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 1d, 03, 09, 00, 0e, 43, 02, 0e, 00, 13, 3e, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 57, 03, 0e, 00, 13, 52, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 5f, 04, 09, 00, 0e, 6b, 02, 0e, 00, 13, 66, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 41, 03, 09, 00, 0e, 6f, 02, 0d, 01, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 31 +Number of expressions: 28 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) @@ -11,29 +11,26 @@ Number of expressions: 31 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(6) - expression 6 operands: lhs = Counter(3), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(4), rhs = Counter(5) -- expression 8 operands: lhs = Counter(5), rhs = Zero -- expression 9 operands: lhs = Counter(6), rhs = Expression(13, Add) -- expression 10 operands: lhs = Counter(7), rhs = Counter(8) -- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(9) -- expression 12 operands: lhs = Counter(6), rhs = Expression(13, Add) -- expression 13 operands: lhs = Counter(7), rhs = Counter(8) -- expression 14 operands: lhs = Counter(7), rhs = Zero -- expression 15 operands: lhs = Counter(9), rhs = Expression(19, Add) -- expression 16 operands: lhs = Counter(10), rhs = Counter(11) -- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(12) -- expression 18 operands: lhs = Counter(9), rhs = Expression(19, Add) -- expression 19 operands: lhs = Counter(10), rhs = Counter(11) -- expression 20 operands: lhs = Counter(12), rhs = Expression(25, Add) -- expression 21 operands: lhs = Counter(13), rhs = Counter(14) -- expression 22 operands: lhs = Expression(23, Add), rhs = Counter(15) -- expression 23 operands: lhs = Counter(12), rhs = Expression(25, Add) -- expression 24 operands: lhs = Counter(13), rhs = Counter(14) -- expression 25 operands: lhs = Counter(13), rhs = Counter(14) +- expression 8 operands: lhs = Counter(6), rhs = Expression(12, Add) +- expression 9 operands: lhs = Counter(7), rhs = Counter(8) +- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(9) +- expression 11 operands: lhs = Counter(6), rhs = Expression(12, Add) +- expression 12 operands: lhs = Counter(7), rhs = Counter(8) +- expression 13 operands: lhs = Counter(9), rhs = Expression(17, Add) +- expression 14 operands: lhs = Counter(10), rhs = Counter(11) +- expression 15 operands: lhs = Expression(16, Add), rhs = Counter(12) +- expression 16 operands: lhs = Counter(9), rhs = Expression(17, Add) +- expression 17 operands: lhs = Counter(10), rhs = Counter(11) +- expression 18 operands: lhs = Counter(12), rhs = Expression(23, Add) +- expression 19 operands: lhs = Counter(13), rhs = Counter(14) +- expression 20 operands: lhs = Expression(21, Add), rhs = Counter(15) +- expression 21 operands: lhs = Counter(12), rhs = Expression(23, Add) +- expression 22 operands: lhs = Counter(13), rhs = Counter(14) +- expression 23 operands: lhs = Counter(13), rhs = Counter(14) +- expression 24 operands: lhs = Counter(15), rhs = Counter(16) +- expression 25 operands: lhs = Expression(26, Add), rhs = Counter(17) - expression 26 operands: lhs = Counter(15), rhs = Counter(16) -- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(17) -- expression 28 operands: lhs = Counter(15), rhs = Counter(16) -- expression 29 operands: lhs = Counter(16), rhs = Zero -- expression 30 operands: lhs = Counter(18), rhs = Counter(17) +- expression 27 operands: lhs = Counter(18), rhs = Counter(17) Number of file 0 mappings: 30 - Code(Counter(0)) at (prev + 3, 1) to (start + 3, 18) - Code(Expression(0, Add)) at (prev + 4, 14) to (start + 0, 19) @@ -48,38 +45,35 @@ Number of file 0 mappings: 30 = ((c3 + (c4 + c5)) - c6) - Code(Counter(5)) at (prev + 1, 22) to (start + 2, 14) - Code(Counter(4)) at (prev + 4, 17) to (start + 0, 25) -- Code(Expression(8, Add)) at (prev + 3, 9) to (start + 0, 14) - = (c5 + Zero) -- Code(Expression(12, Add)) at (prev + 2, 14) to (start + 0, 19) +- Code(Counter(5)) at (prev + 3, 9) to (start + 0, 14) +- Code(Expression(11, Add)) at (prev + 2, 14) to (start + 0, 19) = (c6 + (c7 + c8)) -- Code(Expression(11, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(10, Sub)) at (prev + 1, 15) to (start + 0, 22) = ((c6 + (c7 + c8)) - c9) - Code(Counter(7)) at (prev + 1, 21) to (start + 2, 14) - Code(Counter(8)) at (prev + 4, 17) to (start + 0, 25) -- Code(Expression(14, Add)) at (prev + 3, 9) to (start + 0, 14) - = (c7 + Zero) -- Code(Expression(18, Add)) at (prev + 2, 14) to (start + 0, 19) +- Code(Counter(7)) at (prev + 3, 9) to (start + 0, 14) +- Code(Expression(16, Add)) at (prev + 2, 14) to (start + 0, 19) = (c9 + (c10 + c11)) -- Code(Expression(17, Sub)) at (prev + 1, 12) to (start + 0, 19) +- Code(Expression(15, Sub)) at (prev + 1, 12) to (start + 0, 19) = ((c9 + (c10 + c11)) - c12) - Code(Counter(10)) at (prev + 1, 13) to (start + 0, 21) - Code(Counter(11)) at (prev + 1, 10) to (start + 1, 14) -- Code(Expression(23, Add)) at (prev + 3, 14) to (start + 0, 19) +- Code(Expression(21, Add)) at (prev + 3, 14) to (start + 0, 19) = (c12 + (c13 + c14)) -- Code(Expression(22, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(20, Sub)) at (prev + 1, 15) to (start + 0, 22) = ((c12 + (c13 + c14)) - c15) - Code(Counter(14)) at (prev + 1, 22) to (start + 2, 14) - Code(Counter(13)) at (prev + 3, 18) to (start + 2, 14) -- Code(Expression(25, Add)) at (prev + 4, 9) to (start + 0, 14) +- Code(Expression(23, Add)) at (prev + 4, 9) to (start + 0, 14) = (c13 + c14) -- Code(Expression(28, Add)) at (prev + 2, 14) to (start + 0, 19) +- Code(Expression(26, Add)) at (prev + 2, 14) to (start + 0, 19) = (c15 + c16) -- Code(Expression(27, Sub)) at (prev + 1, 15) to (start + 0, 22) +- Code(Expression(25, Sub)) at (prev + 1, 15) to (start + 0, 22) = ((c15 + c16) - c17) - Code(Counter(16)) at (prev + 1, 22) to (start + 2, 14) - Code(Counter(18)) at (prev + 4, 17) to (start + 0, 22) -- Code(Expression(29, Add)) at (prev + 3, 9) to (start + 0, 14) - = (c16 + Zero) -- Code(Expression(30, Add)) at (prev + 2, 13) to (start + 1, 2) +- Code(Counter(16)) at (prev + 3, 9) to (start + 0, 14) +- Code(Expression(27, Add)) at (prev + 2, 13) to (start + 1, 2) = (c18 + c17) diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage-map/status-quo/dead_code.cov-map index 8d5f88e63efba..0b8a40a8cde05 100644 --- a/tests/coverage-map/status-quo/dead_code.cov-map +++ b/tests/coverage-map/status-quo/dead_code.cov-map @@ -14,23 +14,23 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: dead_code::unused_fn (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 15, 1) to (start + 7, 15) +- Code(Zero) at (prev + 15, 1) to (start + 7, 15) - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: dead_code::unused_pub_fn_not_in_library (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Zero) at (prev + 3, 1) to (start + 7, 15) - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage-map/status-quo/generator.cov-map b/tests/coverage-map/status-quo/generator.cov-map index a66c1af30f992..75704bcc2238a 100644 --- a/tests/coverage-map/status-quo/generator.cov-map +++ b/tests/coverage-map/status-quo/generator.cov-map @@ -14,38 +14,33 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: generator::main -Raw bytes (71): 0x[01, 01, 0b, 01, 00, 05, 0b, 09, 0d, 11, 00, 11, 15, 2a, 19, 11, 15, 15, 19, 26, 00, 2a, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 03, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 07, 01, 0e, 00, 35, 0f, 02, 0b, 00, 2e, 2a, 01, 22, 00, 27, 26, 00, 2c, 00, 2e, 1f, 01, 0e, 00, 35, 23, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 05, 07, 09, 0d, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 11 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) -- expression 2 operands: lhs = Counter(2), rhs = Counter(3) -- expression 3 operands: lhs = Counter(4), rhs = Zero +Number of expressions: 8 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(4), rhs = Counter(5) +- expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(6) - expression 4 operands: lhs = Counter(4), rhs = Counter(5) -- expression 5 operands: lhs = Expression(10, Sub), rhs = Counter(6) -- expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Counter(5), rhs = Counter(6) -- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero -- expression 9 operands: lhs = Expression(10, Sub), rhs = Counter(6) -- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +- expression 5 operands: lhs = Counter(5), rhs = Counter(6) +- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(6) +- expression 7 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 15, 1) to (start + 2, 22) -- Code(Expression(0, Add)) at (prev + 7, 11) to (start + 0, 46) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) -- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) = (c1 + (c2 + c3)) -- Code(Expression(3, Add)) at (prev + 2, 11) to (start + 0, 46) - = (c4 + Zero) -- Code(Expression(10, Sub)) at (prev + 1, 34) to (start + 0, 39) +- Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46) +- Code(Expression(7, Sub)) at (prev + 1, 34) to (start + 0, 39) = (c4 - c5) -- Code(Expression(9, Sub)) at (prev + 0, 44) to (start + 0, 46) +- Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 46) = ((c4 - c5) - c6) -- Code(Expression(7, Add)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(5, Add)) at (prev + 1, 14) to (start + 0, 53) = (c5 + c6) -- Code(Expression(8, Add)) at (prev + 2, 1) to (start + 0, 2) - = (((c4 - c5) - c6) + Zero) +- Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2) + = ((c4 - c5) - c6) Function name: generator::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06] diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage-map/status-quo/inline-dead.cov-map index dec43d3e8bbdd..483f7ef79c637 100644 --- a/tests/coverage-map/status-quo/inline-dead.cov-map +++ b/tests/coverage-map/status-quo/inline-dead.cov-map @@ -1,10 +1,10 @@ Function name: inline_dead::dead (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 2) +- Code(Zero) at (prev + 25, 1) to (start + 2, 2) Function name: inline_dead::live:: Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 10, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] @@ -22,15 +22,13 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: inline_dead::main -Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 04, 01, 03, 0d, 03, 07, 06, 02, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 07, 06, 02, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) -- Code(Expression(0, Add)) at (prev + 7, 6) to (start + 2, 2) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 7, 6) to (start + 2, 2) Function name: inline_dead::main::{closure#0} Raw bytes (16): 0x[01, 01, 01, 01, 05, 02, 00, 09, 0d, 00, 0e, 03, 02, 05, 00, 06] diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage-map/status-quo/inline.cov-map index 57ae85623fb75..72b10fd0cc278 100644 --- a/tests/coverage-map/status-quo/inline.cov-map +++ b/tests/coverage-map/status-quo/inline.cov-map @@ -1,19 +1,17 @@ Function name: inline::display:: -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 00, 03, 05, 05, 01, 29, 01, 00, 22, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 10, 07, 00, 11, 02, 06, 0a, 03, 05, 01, 02] +Raw bytes (33): 0x[01, 01, 02, 01, 05, 03, 05, 05, 01, 29, 01, 00, 22, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 10, 05, 00, 11, 02, 06, 06, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 3 +Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(1), rhs = Zero -- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(1) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 41, 1) to (start + 0, 34) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 16) = (c0 + c1) -- Code(Expression(1, Add)) at (prev + 0, 17) to (start + 2, 6) - = (c1 + Zero) -- Code(Expression(2, Sub)) at (prev + 3, 5) to (start + 1, 2) +- Code(Counter(1)) at (prev + 0, 17) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 3, 5) to (start + 1, 2) = ((c0 + c1) - c1) Function name: inline::error @@ -41,15 +39,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2) Function name: inline::permutate:: -Raw bytes (54): 0x[01, 01, 05, 01, 05, 02, 0d, 11, 00, 05, 13, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 0b, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0f, 03, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 04, 01, 05, 02, 0d, 05, 0f, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 11, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 4 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(3) -- expression 2 operands: lhs = Counter(4), rhs = Zero -- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) -- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(1), rhs = Expression(3, Add) +- expression 3 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 15, 1) to (start + 2, 14) - Code(Counter(1)) at (prev + 2, 15) to (start + 2, 6) @@ -58,10 +55,9 @@ Number of file 0 mappings: 8 - Code(Counter(4)) at (prev + 1, 13) to (start + 0, 14) - Code(Expression(1, Sub)) at (prev + 0, 18) to (start + 0, 22) = ((c0 - c1) - c3) -- Code(Expression(2, Add)) at (prev + 0, 23) to (start + 4, 10) - = (c4 + Zero) +- Code(Counter(4)) at (prev + 0, 23) to (start + 4, 10) - Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6) -- Code(Expression(3, Add)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c2 + c3)) Function name: inline::permutations:: diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage-map/status-quo/issue-93054.cov-map index 52fe7f58d15d8..c2c6e9a651673 100644 --- a/tests/coverage-map/status-quo/issue-93054.cov-map +++ b/tests/coverage-map/status-quo/issue-93054.cov-map @@ -1,10 +1,10 @@ Function name: issue_93054::foo2 (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 1d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 29) +- Code(Zero) at (prev + 22, 1) to (start + 0, 29) Function name: issue_93054::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d] @@ -15,10 +15,10 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13) Function name: issue_93054::make (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1a, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 2) +- Code(Zero) at (prev + 26, 1) to (start + 2, 2) diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage-map/status-quo/lazy_boolean.cov-map index b18a964043355..0ad393c40fa77 100644 --- a/tests/coverage-map/status-quo/lazy_boolean.cov-map +++ b/tests/coverage-map/status-quo/lazy_boolean.cov-map @@ -1,223 +1,219 @@ Function name: lazy_boolean::main -Raw bytes (646): 0x[01, 01, a8, 01, 01, 05, 09, 9a, 05, 9f, 05, 09, 05, 02, 05, 02, 9f, 05, 09, 05, 02, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 00, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 8f, 05, 00, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 87, 05, 00, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 00, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 25, e2, 04, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 97, 05, 02, 09, 00, 11, 9f, 05, 02, 0d, 00, 12, 9a, 05, 02, 0d, 00, 12, 8f, 05, 03, 09, 00, 11, 33, 02, 0d, 00, 12, 92, 05, 02, 0d, 00, 12, 87, 05, 02, 09, 00, 11, 6f, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ff, 04, 01, 09, 00, 11, ab, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, cb, 01, 04, 09, 00, 10, fa, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, f7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, f2, 04, 05, 05, 03, 06, ef, 04, 05, 09, 00, 10, ea, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, e7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, e2, 04, 02, 0c, 02, 06, df, 04, 03, 01, 00, 02] +Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 04, 09, 00, 10, ea, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 09, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 168 +Number of expressions: 164 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 2 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 1 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 2 operands: lhs = Expression(163, Add), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) - expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 5 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 5 operands: lhs = Expression(163, Add), rhs = Counter(2) - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 7 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 8 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 9 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 10 operands: lhs = Expression(167, Add), rhs = Counter(2) +- expression 7 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 8 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 9 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 10 operands: lhs = Expression(163, Add), rhs = Counter(2) - expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 12 operands: lhs = Expression(165, Add), rhs = Zero -- expression 13 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 14 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 16 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 17 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 18 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 19 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 20 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 21 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 22 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 23 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 24 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 25 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 26 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 27 operands: lhs = Expression(163, Add), rhs = Zero -- expression 28 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 29 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 30 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 31 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 32 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 33 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 34 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 35 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 36 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 37 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 38 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 39 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 40 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 41 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 42 operands: lhs = Expression(161, Add), rhs = Zero -- expression 43 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 44 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 45 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 46 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 47 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 48 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 49 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 50 operands: lhs = Expression(159, Add), rhs = Zero -- expression 51 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 52 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 53 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 54 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 55 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 56 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 57 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 58 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 59 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 60 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 61 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 62 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 63 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 64 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 65 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 66 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 67 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 68 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 69 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 70 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 71 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 72 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 73 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 74 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 75 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 76 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 77 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 78 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 79 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 80 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 81 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 82 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 83 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 84 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 85 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 86 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 87 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 88 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 89 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 90 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 91 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 92 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 93 operands: lhs = Counter(7), rhs = Expression(156, Sub) -- expression 94 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 95 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 96 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 97 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 98 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 99 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 100 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 101 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 102 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 103 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 104 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 105 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 106 operands: lhs = Expression(155, Add), rhs = Counter(8) -- expression 107 operands: lhs = Counter(7), rhs = Expression(156, Sub) -- expression 108 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 109 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 110 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 111 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 112 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 113 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 114 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 115 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 116 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 117 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 118 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 119 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 120 operands: lhs = Counter(8), rhs = Expression(154, Sub) -- expression 121 operands: lhs = Expression(155, Add), rhs = Counter(8) -- expression 122 operands: lhs = Counter(7), rhs = Expression(156, Sub) -- expression 123 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 124 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 125 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 126 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 127 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 128 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 129 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 130 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 131 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 132 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 133 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 134 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 135 operands: lhs = Expression(153, Add), rhs = Counter(9) -- expression 136 operands: lhs = Counter(8), rhs = Expression(154, Sub) -- expression 137 operands: lhs = Expression(155, Add), rhs = Counter(8) -- expression 138 operands: lhs = Counter(7), rhs = Expression(156, Sub) -- expression 139 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 140 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 141 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 142 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 143 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 144 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 145 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 146 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 147 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 148 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 149 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 150 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 151 operands: lhs = Counter(9), rhs = Expression(152, Sub) -- expression 152 operands: lhs = Expression(153, Add), rhs = Counter(9) -- expression 153 operands: lhs = Counter(8), rhs = Expression(154, Sub) -- expression 154 operands: lhs = Expression(155, Add), rhs = Counter(8) -- expression 155 operands: lhs = Counter(7), rhs = Expression(156, Sub) -- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(7) -- expression 157 operands: lhs = Counter(6), rhs = Expression(158, Sub) -- expression 158 operands: lhs = Expression(159, Add), rhs = Counter(6) -- expression 159 operands: lhs = Counter(5), rhs = Expression(160, Sub) -- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(5) -- expression 161 operands: lhs = Counter(4), rhs = Expression(162, Sub) -- expression 162 operands: lhs = Expression(163, Add), rhs = Counter(4) -- expression 163 operands: lhs = Counter(3), rhs = Expression(164, Sub) -- expression 164 operands: lhs = Expression(165, Add), rhs = Counter(3) -- expression 165 operands: lhs = Counter(2), rhs = Expression(166, Sub) -- expression 166 operands: lhs = Expression(167, Add), rhs = Counter(2) -- expression 167 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 12 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 13 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 14 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 15 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 16 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 17 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 18 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 19 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 20 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 21 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 22 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 23 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 24 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 25 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 26 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 27 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 28 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 29 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 30 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 31 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 32 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 33 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 34 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 35 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 36 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 37 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 38 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 39 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 40 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 41 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 42 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 43 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 44 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 45 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 46 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 47 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 48 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 49 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 50 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 51 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 52 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 53 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 54 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 55 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 56 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 57 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 58 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 59 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 60 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 61 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 62 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 63 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 64 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 65 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 66 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 67 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 68 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 69 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 70 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 71 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 72 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 73 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 74 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 75 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 76 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 77 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 78 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 79 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 80 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 81 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 82 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 83 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 84 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 85 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 86 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 87 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 88 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 89 operands: lhs = Counter(7), rhs = Expression(152, Sub) +- expression 90 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 91 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 92 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 93 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 94 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 95 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 96 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 97 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 98 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 99 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 100 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 101 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 102 operands: lhs = Expression(151, Add), rhs = Counter(8) +- expression 103 operands: lhs = Counter(7), rhs = Expression(152, Sub) +- expression 104 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 105 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 106 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 107 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 108 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 109 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 110 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 111 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 112 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 113 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 114 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 115 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 116 operands: lhs = Counter(8), rhs = Expression(150, Sub) +- expression 117 operands: lhs = Expression(151, Add), rhs = Counter(8) +- expression 118 operands: lhs = Counter(7), rhs = Expression(152, Sub) +- expression 119 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 120 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 121 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 122 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 123 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 124 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 125 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 126 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 127 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 128 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 129 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 130 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 131 operands: lhs = Expression(149, Add), rhs = Counter(9) +- expression 132 operands: lhs = Counter(8), rhs = Expression(150, Sub) +- expression 133 operands: lhs = Expression(151, Add), rhs = Counter(8) +- expression 134 operands: lhs = Counter(7), rhs = Expression(152, Sub) +- expression 135 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 136 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 137 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 138 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 139 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 140 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 141 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 142 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 143 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 144 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 145 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 146 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 147 operands: lhs = Counter(9), rhs = Expression(148, Sub) +- expression 148 operands: lhs = Expression(149, Add), rhs = Counter(9) +- expression 149 operands: lhs = Counter(8), rhs = Expression(150, Sub) +- expression 150 operands: lhs = Expression(151, Add), rhs = Counter(8) +- expression 151 operands: lhs = Counter(7), rhs = Expression(152, Sub) +- expression 152 operands: lhs = Expression(153, Add), rhs = Counter(7) +- expression 153 operands: lhs = Counter(6), rhs = Expression(154, Sub) +- expression 154 operands: lhs = Expression(155, Add), rhs = Counter(6) +- expression 155 operands: lhs = Counter(5), rhs = Expression(156, Sub) +- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(5) +- expression 157 operands: lhs = Counter(4), rhs = Expression(158, Sub) +- expression 158 operands: lhs = Expression(159, Add), rhs = Counter(4) +- expression 159 operands: lhs = Counter(3), rhs = Expression(160, Sub) +- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(3) +- expression 161 operands: lhs = Counter(2), rhs = Expression(162, Sub) +- expression 162 operands: lhs = Expression(163, Add), rhs = Counter(2) +- expression 163 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 28 - Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) -- Code(Expression(165, Add)) at (prev + 2, 9) to (start + 0, 17) +- Code(Expression(161, Add)) at (prev + 2, 9) to (start + 0, 17) = (c2 + ((c1 + (c0 - c1)) - c2)) -- Code(Expression(167, Add)) at (prev + 2, 13) to (start + 0, 18) +- Code(Expression(163, Add)) at (prev + 2, 13) to (start + 0, 18) = (c1 + (c0 - c1)) -- Code(Expression(166, Sub)) at (prev + 2, 13) to (start + 0, 18) +- Code(Expression(162, Sub)) at (prev + 2, 13) to (start + 0, 18) = ((c1 + (c0 - c1)) - c2) -- Code(Expression(163, Add)) at (prev + 3, 9) to (start + 0, 17) +- Code(Expression(159, Add)) at (prev + 3, 9) to (start + 0, 17) = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) -- Code(Expression(12, Add)) at (prev + 2, 13) to (start + 0, 18) - = ((c2 + ((c1 + (c0 - c1)) - c2)) + Zero) -- Code(Expression(164, Sub)) at (prev + 2, 13) to (start + 0, 18) +- Code(Expression(161, Add)) at (prev + 2, 13) to (start + 0, 18) + = (c2 + ((c1 + (c0 - c1)) - c2)) +- Code(Expression(160, Sub)) at (prev + 2, 13) to (start + 0, 18) = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3) -- Code(Expression(161, Add)) at (prev + 2, 9) to (start + 0, 17) +- Code(Expression(157, Add)) at (prev + 2, 9) to (start + 0, 17) = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) -- Code(Expression(27, Add)) at (prev + 0, 20) to (start + 0, 25) - = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + Zero) +- Code(Expression(159, Add)) at (prev + 0, 20) to (start + 0, 25) + = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - Code(Counter(4)) at (prev + 0, 29) to (start + 0, 34) -- Code(Expression(159, Add)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(155, Add)) at (prev + 1, 9) to (start + 0, 17) = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) -- Code(Expression(42, Add)) at (prev + 0, 20) to (start + 0, 25) - = ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) + Zero) +- Code(Expression(157, Add)) at (prev + 0, 20) to (start + 0, 25) + = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34) -- Code(Expression(50, Add)) at (prev + 4, 9) to (start + 0, 16) - = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) + Zero) -- Code(Expression(158, Sub)) at (prev + 1, 5) to (start + 3, 6) +- Code(Expression(155, Add)) at (prev + 4, 9) to (start + 0, 16) + = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) +- Code(Expression(154, Sub)) at (prev + 1, 5) to (start + 3, 6) = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6) - Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7) -- Code(Expression(157, Add)) at (prev + 3, 9) to (start + 0, 16) +- Code(Expression(153, Add)) at (prev + 3, 9) to (start + 0, 16) = (c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6) -- Code(Expression(156, Sub)) at (prev + 5, 5) to (start + 3, 6) +- Code(Expression(152, Sub)) at (prev + 5, 5) to (start + 3, 6) = ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7) -- Code(Expression(155, Add)) at (prev + 5, 9) to (start + 0, 16) +- Code(Expression(151, Add)) at (prev + 5, 9) to (start + 0, 16) = (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) -- Code(Expression(154, Sub)) at (prev + 0, 17) to (start + 2, 6) +- Code(Expression(150, Sub)) at (prev + 0, 17) to (start + 2, 6) = ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8) - Code(Counter(8)) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(153, Add)) at (prev + 2, 8) to (start + 0, 15) +- Code(Expression(149, Add)) at (prev + 2, 8) to (start + 0, 15) = (c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - Code(Counter(9)) at (prev + 0, 16) to (start + 2, 6) -- Code(Expression(152, Sub)) at (prev + 2, 12) to (start + 2, 6) +- Code(Expression(148, Sub)) at (prev + 2, 12) to (start + 2, 6) = ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9) -- Code(Expression(151, Add)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(147, Add)) at (prev + 3, 1) to (start + 0, 2) = (c9 + ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9)) diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map index 56fafc0a67b1f..ebace8cbd7131 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -1,62 +1,57 @@ Function name: ::fmt -Raw bytes (262): 0x[01, 01, 36, 05, 09, 0a, 02, 00, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 25, b3, 01, b6, 01, 19, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ca, 01, 03, 0d, 00, 0e, cf, 01, 00, 12, 00, 17, 2b, 01, 10, 00, 14, c6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c2, 01, 01, 12, 00, 13, bb, 01, 01, 11, 00, 22, b6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, af, 01, 01, 05, 00, 06] +Raw bytes (249): 0x[01, 01, 31, 05, 09, 00, 02, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, bf, 01, c3, 01, 0d, 00, 11, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, ab, 01, 11, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 25, a3, 01, a6, 01, 19, ab, 01, 11, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, b6, 01, 03, 0d, 00, 0e, bb, 01, 00, 12, 00, 17, b6, 01, 01, 10, 00, 14, b2, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, ae, 01, 01, 12, 00, 13, ab, 01, 01, 11, 00, 22, a6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 9f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 54 +Number of expressions: 49 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -- expression 1 operands: lhs = Expression(2, Sub), rhs = Expression(0, Sub) -- expression 2 operands: lhs = Zero, rhs = Zero -- expression 3 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 4 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 5 operands: lhs = Counter(3), rhs = Zero -- expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 8 operands: lhs = Counter(3), rhs = Zero -- expression 9 operands: lhs = Counter(4), rhs = Counter(5) -- expression 10 operands: lhs = Expression(50, Sub), rhs = Zero -- expression 11 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 12 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 13 operands: lhs = Counter(3), rhs = Zero -- expression 14 operands: lhs = Counter(4), rhs = Counter(5) -- expression 15 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 16 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 17 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 18 operands: lhs = Counter(3), rhs = Zero -- expression 19 operands: lhs = Counter(4), rhs = Counter(5) -- expression 20 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 21 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 22 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 23 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 24 operands: lhs = Counter(3), rhs = Zero -- expression 25 operands: lhs = Counter(4), rhs = Counter(5) -- expression 26 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 27 operands: lhs = Zero, rhs = Zero -- expression 28 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 29 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 30 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 31 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 32 operands: lhs = Counter(3), rhs = Zero -- expression 33 operands: lhs = Counter(4), rhs = Counter(5) -- expression 34 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 35 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 36 operands: lhs = Zero, rhs = Zero -- expression 37 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 38 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 39 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 40 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 41 operands: lhs = Counter(3), rhs = Zero -- expression 42 operands: lhs = Counter(4), rhs = Counter(5) -- expression 43 operands: lhs = Counter(9), rhs = Expression(44, Add) -- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(6) -- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 46 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 47 operands: lhs = Zero, rhs = Zero -- expression 48 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 52 operands: lhs = Counter(3), rhs = Zero -- expression 53 operands: lhs = Counter(4), rhs = Counter(5) +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 3 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 4 operands: lhs = Counter(3), rhs = Zero +- expression 5 operands: lhs = Counter(4), rhs = Counter(5) +- expression 6 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 7 operands: lhs = Counter(3), rhs = Zero +- expression 8 operands: lhs = Counter(4), rhs = Counter(5) +- expression 9 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 10 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 11 operands: lhs = Counter(3), rhs = Zero +- expression 12 operands: lhs = Counter(4), rhs = Counter(5) +- expression 13 operands: lhs = Expression(45, Sub), rhs = Counter(5) +- expression 14 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 15 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 16 operands: lhs = Counter(3), rhs = Zero +- expression 17 operands: lhs = Counter(4), rhs = Counter(5) +- expression 18 operands: lhs = Expression(44, Sub), rhs = Counter(7) +- expression 19 operands: lhs = Expression(45, Sub), rhs = Counter(5) +- expression 20 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 21 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 22 operands: lhs = Counter(3), rhs = Zero +- expression 23 operands: lhs = Counter(4), rhs = Counter(5) +- expression 24 operands: lhs = Zero, rhs = Expression(43, Sub) +- expression 25 operands: lhs = Expression(44, Sub), rhs = Counter(7) +- expression 26 operands: lhs = Expression(45, Sub), rhs = Counter(5) +- expression 27 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 28 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 29 operands: lhs = Counter(3), rhs = Zero +- expression 30 operands: lhs = Counter(4), rhs = Counter(5) +- expression 31 operands: lhs = Expression(42, Add), rhs = Counter(4) +- expression 32 operands: lhs = Zero, rhs = Expression(43, Sub) +- expression 33 operands: lhs = Expression(44, Sub), rhs = Counter(7) +- expression 34 operands: lhs = Expression(45, Sub), rhs = Counter(5) +- expression 35 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 36 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 37 operands: lhs = Counter(3), rhs = Zero +- expression 38 operands: lhs = Counter(4), rhs = Counter(5) +- expression 39 operands: lhs = Counter(9), rhs = Expression(40, Add) +- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(6) +- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(4) +- expression 42 operands: lhs = Zero, rhs = Expression(43, Sub) +- expression 43 operands: lhs = Expression(44, Sub), rhs = Counter(7) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(5) +- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(6) +- expression 46 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) +- expression 47 operands: lhs = Counter(3), rhs = Zero +- expression 48 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) @@ -65,91 +60,86 @@ Number of file 0 mappings: 20 - Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 15) = (c1 - c2) - Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 30) - = ((Zero - Zero) + (c1 - c2)) + = (Zero + (c1 - c2)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) -- Code(Expression(50, Sub)) at (prev + 3, 13) to (start + 0, 14) +- Code(Expression(45, Sub)) at (prev + 3, 13) to (start + 0, 14) = (((c3 + Zero) + (c4 + c5)) - c6) -- Code(Expression(51, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(46, Add)) at (prev + 0, 18) to (start + 0, 23) = ((c3 + Zero) + (c4 + c5)) -- Code(Expression(10, Add)) at (prev + 1, 16) to (start + 0, 20) - = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero) -- Code(Expression(49, Sub)) at (prev + 1, 20) to (start + 0, 25) +- Code(Expression(45, Sub)) at (prev + 1, 16) to (start + 0, 20) + = (((c3 + Zero) + (c4 + c5)) - c6) +- Code(Expression(44, Sub)) at (prev + 1, 20) to (start + 0, 25) = ((((c3 + Zero) + (c4 + c5)) - c6) - c5) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(48, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(43, Sub)) at (prev + 1, 18) to (start + 0, 19) = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7) -- Code(Expression(46, Add)) at (prev + 1, 17) to (start + 0, 34) - = ((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) -- Code(Expression(45, Sub)) at (prev + 0, 34) to (start + 0, 35) - = (((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) +- Code(Expression(42, Add)) at (prev + 1, 17) to (start + 0, 34) + = (Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) +- Code(Expression(41, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(43, Add)) at (prev + 1, 5) to (start + 0, 6) - = (c9 + ((((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) +- Code(Expression(39, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + (((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) Function name: ::fmt -Raw bytes (266): 0x[01, 01, 38, 01, 05, 02, 09, 0e, 12, 00, 00, 02, 09, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 00, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ba, 01, df, 01, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 12, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ce, 01, 02, 0d, 00, 0e, d3, 01, 00, 12, 00, 17, 33, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ca, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c6, 01, 01, 12, 00, 13, bf, 01, 01, 11, 00, 22, ba, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, b7, 01, 01, 05, 00, 06] +Raw bytes (253): 0x[01, 01, 33, 01, 05, 02, 09, 00, 0e, 02, 09, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, c3, 01, c7, 01, 05, 0d, 11, 15, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, af, 01, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, aa, 01, cb, 01, af, 01, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ba, 01, 02, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, ba, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, b6, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, a7, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 56 +Number of expressions: 51 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 2 operands: lhs = Expression(3, Sub), rhs = Expression(4, Sub) -- expression 3 operands: lhs = Zero, rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 5 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 6 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 7 operands: lhs = Counter(1), rhs = Counter(3) -- expression 8 operands: lhs = Counter(4), rhs = Counter(5) -- expression 9 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 10 operands: lhs = Counter(1), rhs = Counter(3) -- expression 11 operands: lhs = Counter(4), rhs = Counter(5) -- expression 12 operands: lhs = Expression(51, Sub), rhs = Zero -- expression 13 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 14 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 15 operands: lhs = Counter(1), rhs = Counter(3) -- expression 16 operands: lhs = Counter(4), rhs = Counter(5) -- expression 17 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 18 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 19 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 20 operands: lhs = Counter(1), rhs = Counter(3) -- expression 21 operands: lhs = Counter(4), rhs = Counter(5) -- expression 22 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 23 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 24 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 25 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 26 operands: lhs = Counter(1), rhs = Counter(3) -- expression 27 operands: lhs = Counter(4), rhs = Counter(5) -- expression 28 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 29 operands: lhs = Zero, rhs = Zero -- expression 30 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 31 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 32 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 33 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 34 operands: lhs = Counter(1), rhs = Counter(3) -- expression 35 operands: lhs = Counter(4), rhs = Counter(5) -- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(5) -- expression 37 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 38 operands: lhs = Zero, rhs = Zero -- expression 39 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 40 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 41 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 42 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 43 operands: lhs = Counter(1), rhs = Counter(3) -- expression 44 operands: lhs = Counter(4), rhs = Counter(5) -- expression 45 operands: lhs = Expression(46, Sub), rhs = Expression(55, Add) -- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(5) -- expression 47 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 48 operands: lhs = Zero, rhs = Zero -- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 50 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 52 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 53 operands: lhs = Counter(1), rhs = Counter(3) -- expression 54 operands: lhs = Counter(4), rhs = Counter(5) -- expression 55 operands: lhs = Counter(6), rhs = Counter(9) +- expression 2 operands: lhs = Zero, rhs = Expression(3, Sub) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 4 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 5 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 6 operands: lhs = Counter(1), rhs = Counter(3) +- expression 7 operands: lhs = Counter(4), rhs = Counter(5) +- expression 8 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 9 operands: lhs = Counter(1), rhs = Counter(3) +- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +- expression 11 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 12 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 13 operands: lhs = Counter(1), rhs = Counter(3) +- expression 14 operands: lhs = Counter(4), rhs = Counter(5) +- expression 15 operands: lhs = Expression(46, Sub), rhs = Counter(4) +- expression 16 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 17 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 18 operands: lhs = Counter(1), rhs = Counter(3) +- expression 19 operands: lhs = Counter(4), rhs = Counter(5) +- expression 20 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 21 operands: lhs = Expression(46, Sub), rhs = Counter(4) +- expression 22 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 24 operands: lhs = Counter(1), rhs = Counter(3) +- expression 25 operands: lhs = Counter(4), rhs = Counter(5) +- expression 26 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 27 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 28 operands: lhs = Expression(46, Sub), rhs = Counter(4) +- expression 29 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 30 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 31 operands: lhs = Counter(1), rhs = Counter(3) +- expression 32 operands: lhs = Counter(4), rhs = Counter(5) +- expression 33 operands: lhs = Expression(43, Add), rhs = Counter(5) +- expression 34 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 35 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 36 operands: lhs = Expression(46, Sub), rhs = Counter(4) +- expression 37 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 38 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 39 operands: lhs = Counter(1), rhs = Counter(3) +- expression 40 operands: lhs = Counter(4), rhs = Counter(5) +- expression 41 operands: lhs = Expression(42, Sub), rhs = Expression(50, Add) +- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(5) +- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(4) +- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 48 operands: lhs = Counter(1), rhs = Counter(3) +- expression 49 operands: lhs = Counter(4), rhs = Counter(5) +- expression 50 operands: lhs = Counter(6), rhs = Counter(9) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) @@ -157,31 +147,31 @@ Number of file 0 mappings: 20 = (c0 - c1) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(3, Sub)) at (prev + 1, 14) to (start + 0, 15) = ((c0 - c1) - c2) - Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) - = ((Zero - Zero) + ((c0 - c1) - c2)) + = (Zero + ((c0 - c1) - c2)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(51, Sub)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(46, Sub)) at (prev + 2, 13) to (start + 0, 14) = (((c1 + c3) + (c4 + c5)) - c6) -- Code(Expression(52, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23) = ((c1 + c3) + (c4 + c5)) -- Code(Expression(12, Add)) at (prev + 1, 16) to (start + 0, 21) - = ((((c1 + c3) + (c4 + c5)) - c6) + Zero) +- Code(Expression(46, Sub)) at (prev + 1, 16) to (start + 0, 21) + = (((c1 + c3) + (c4 + c5)) - c6) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(50, Sub)) at (prev + 2, 20) to (start + 0, 25) +- Code(Expression(45, Sub)) at (prev + 2, 20) to (start + 0, 25) = ((((c1 + c3) + (c4 + c5)) - c6) - c4) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(49, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19) = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) -- Code(Expression(47, Add)) at (prev + 1, 17) to (start + 0, 34) - = ((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) -- Code(Expression(46, Sub)) at (prev + 0, 34) to (start + 0, 35) - = (((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) +- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34) + = (Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) +- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(45, Add)) at (prev + 1, 5) to (start + 0, 6) - = ((((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) +- Code(Expression(41, Add)) at (prev + 1, 5) to (start + 0, 6) + = (((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage-map/status-quo/no_cov_crate.cov-map index 7ab5995dc2892..05b6448bbd24a 100644 --- a/tests/coverage-map/status-quo/no_cov_crate.cov-map +++ b/tests/coverage-map/status-quo/no_cov_crate.cov-map @@ -15,12 +15,12 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) Function name: no_cov_crate::add_coverage_not_called (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +- Code(Zero) at (prev + 29, 1) to (start + 2, 2) Function name: no_cov_crate::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 4d, 01, 0b, 02] diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage-map/status-quo/partial_eq.cov-map index dd61cd77ab619..3549116db7ad3 100644 --- a/tests/coverage-map/status-quo/partial_eq.cov-map +++ b/tests/coverage-map/status-quo/partial_eq.cov-map @@ -1,27 +1,27 @@ Function name: ::clone (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 0f] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 04, 0a, 00, 0f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 4, 10) to (start + 0, 15) +- Code(Zero) at (prev + 4, 10) to (start + 0, 15) Function name: ::cmp (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 33, 00, 34, 00, 00, 35, 00, 36] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 33, 00, 34, 00, 00, 35, 00, 36] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 4, 51) to (start + 0, 52) +- Code(Zero) at (prev + 4, 51) to (start + 0, 52) - Code(Zero) at (prev + 0, 53) to (start + 0, 54) Function name: ::eq (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 18, 00, 19, 00, 00, 20, 00, 21] +Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 18, 00, 19, 00, 00, 20, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 4, 24) to (start + 0, 25) +- Code(Zero) at (prev + 4, 24) to (start + 0, 25) - Code(Zero) at (prev + 0, 32) to (start + 0, 33) Function name: ::partial_cmp diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage-map/status-quo/simple_loop.cov-map index eb49c2324ccce..f1691ffc5e6a0 100644 --- a/tests/coverage-map/status-quo/simple_loop.cov-map +++ b/tests/coverage-map/status-quo/simple_loop.cov-map @@ -1,28 +1,27 @@ Function name: simple_loop::main -Raw bytes (59): 0x[01, 01, 0a, 01, 05, 27, 09, 05, 02, 23, 09, 27, 09, 05, 02, 1e, 00, 23, 09, 27, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 23, 05, 0d, 02, 0e, 1e, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1b, 06, 01, 00, 02] +Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 10 +Number of expressions: 9 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Expression(9, Add), rhs = Counter(2) +- expression 1 operands: lhs = Expression(8, Add), rhs = Counter(2) - expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 3 operands: lhs = Expression(8, Add), rhs = Counter(2) -- expression 4 operands: lhs = Expression(9, Add), rhs = Counter(2) +- expression 3 operands: lhs = Expression(7, Add), rhs = Counter(2) +- expression 4 operands: lhs = Expression(8, Add), rhs = Counter(2) - expression 5 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero +- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(2) - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(2) -- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(2) -- expression 9 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 8 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 3, 1) to (start + 9, 16) - Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) -- Code(Expression(8, Add)) at (prev + 5, 13) to (start + 2, 14) +- Code(Expression(7, Add)) at (prev + 5, 13) to (start + 2, 14) = ((c1 + (c0 - c1)) + c2) -- Code(Expression(7, Sub)) at (prev + 4, 13) to (start + 0, 18) +- Code(Expression(6, Sub)) at (prev + 4, 13) to (start + 0, 18) = (((c1 + (c0 - c1)) + c2) - c2) - Code(Counter(2)) at (prev + 2, 10) to (start + 3, 10) -- Code(Expression(6, Add)) at (prev + 6, 1) to (start + 0, 2) - = ((((c1 + (c0 - c1)) + c2) - c2) + Zero) +- Code(Expression(6, Sub)) at (prev + 6, 1) to (start + 0, 2) + = (((c1 + (c0 - c1)) + c2) - c2) diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage-map/status-quo/simple_match.cov-map index d5389f04b2615..4a32745d29293 100644 --- a/tests/coverage-map/status-quo/simple_match.cov-map +++ b/tests/coverage-map/status-quo/simple_match.cov-map @@ -1,36 +1,33 @@ Function name: simple_match::main -Raw bytes (82): 0x[01, 01, 0e, 01, 05, 2f, 33, 05, 02, 09, 0d, 2b, 11, 2f, 33, 05, 02, 09, 0d, 26, 00, 2b, 11, 2f, 33, 05, 02, 09, 0d, 09, 00, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 2b, 05, 09, 00, 0d, 26, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 23, 02, 11, 02, 12, 37, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 14 +Number of expressions: 12 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) +- expression 1 operands: lhs = Expression(10, Add), rhs = Expression(11, Add) - expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) -- expression 4 operands: lhs = Expression(10, Add), rhs = Counter(4) -- expression 5 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) +- expression 4 operands: lhs = Expression(9, Add), rhs = Counter(4) +- expression 5 operands: lhs = Expression(10, Add), rhs = Expression(11, Add) - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) -- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero -- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(4) -- expression 10 operands: lhs = Expression(11, Add), rhs = Expression(12, Add) -- expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub) -- expression 12 operands: lhs = Counter(2), rhs = Counter(3) -- expression 13 operands: lhs = Counter(2), rhs = Zero +- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(4) +- expression 9 operands: lhs = Expression(10, Add), rhs = Expression(11, Add) +- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) -- Code(Expression(10, Add)) at (prev + 5, 9) to (start + 0, 13) +- Code(Expression(9, Add)) at (prev + 5, 9) to (start + 0, 13) = ((c1 + (c0 - c1)) + (c2 + c3)) -- Code(Expression(9, Sub)) at (prev + 5, 13) to (start + 0, 22) +- Code(Expression(8, Sub)) at (prev + 5, 13) to (start + 0, 22) = (((c1 + (c0 - c1)) + (c2 + c3)) - c4) - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) -- Code(Expression(8, Add)) at (prev + 2, 17) to (start + 2, 18) - = ((((c1 + (c0 - c1)) + (c2 + c3)) - c4) + Zero) -- Code(Expression(13, Add)) at (prev + 4, 13) to (start + 7, 14) - = (c2 + Zero) +- Code(Expression(8, Sub)) at (prev + 2, 17) to (start + 2, 18) + = (((c1 + (c0 - c1)) + (c2 + c3)) - c4) +- Code(Counter(2)) at (prev + 4, 13) to (start + 7, 14) - Code(Counter(3)) at (prev + 10, 13) to (start + 0, 15) - Code(Counter(4)) at (prev + 3, 1) to (start + 0, 2) diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage-map/status-quo/test_harness.cov-map index b0e955dd142a5..6940d2e282430 100644 --- a/tests/coverage-map/status-quo/test_harness.cov-map +++ b/tests/coverage-map/status-quo/test_harness.cov-map @@ -15,10 +15,10 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 1) to (start + 0, 8) Function name: test_harness::unused (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 0f] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 15) +- Code(Zero) at (prev + 7, 1) to (start + 0, 15) diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/status-quo/try_error_result.cov-map index b52e78d1195ab..8367103a21a4e 100644 --- a/tests/coverage-map/status-quo/try_error_result.cov-map +++ b/tests/coverage-map/status-quo/try_error_result.cov-map @@ -91,136 +91,130 @@ Number of file 0 mappings: 11 = ((c4 + (c5 + c6)) + c3) Function name: try_error_result::test2 -Raw bytes (373): 0x[01, 01, 41, 01, 07, 05, 09, 03, 0d, 41, 11, 52, 15, 41, 11, 4a, 1d, 4e, 19, 52, 15, 41, 11, 4e, 00, 52, 15, 41, 11, 4e, 19, 52, 15, 41, 11, 46, 00, 4a, 1d, 4e, 19, 52, 15, 41, 11, 6a, 25, 49, 21, 49, 21, 66, 00, 6a, 25, 49, 21, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, a2, 01, 41, 03, 0d, 9e, 01, 29, a2, 01, 41, 03, 0d, 96, 01, 00, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, ba, 01, 35, 45, 31, 45, 31, b6, 01, 00, ba, 01, 35, 45, 31, d2, 01, 3d, 4d, 39, 4d, 39, ce, 01, 00, d2, 01, 3d, 4d, 39, db, 01, 0d, 11, df, 01, e3, 01, f3, 01, 15, e7, 01, eb, 01, ef, 01, 19, 1d, 21, 25, f7, 01, fb, 01, 29, 2d, ff, 01, 83, 02, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, a2, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 52, 00, 31, 03, 35, 15, 04, 11, 00, 12, 4e, 02, 11, 04, 12, 46, 05, 11, 00, 14, 2b, 00, 17, 00, 41, 19, 00, 41, 00, 42, 4a, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 43, 01, 0d, 00, 20, 66, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 6a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 63, 01, 0d, 00, 20, 96, 01, 04, 11, 00, 14, 9e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 9a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 93, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, ba, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, b3, 01, 01, 0d, 00, 20, ce, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, d2, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, cb, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, d7, 01, 01, 01, 00, 02] +Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, 11, c7, 01, cb, 01, db, 01, 15, cf, 01, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 65 +Number of expressions: 59 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(16), rhs = Counter(4) -- expression 4 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Expression(18, Sub), rhs = Counter(5) - expression 5 operands: lhs = Counter(16), rhs = Counter(4) -- expression 6 operands: lhs = Expression(18, Sub), rhs = Counter(7) -- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(6) -- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 6 operands: lhs = Expression(16, Sub), rhs = Counter(7) +- expression 7 operands: lhs = Expression(17, Sub), rhs = Counter(6) +- expression 8 operands: lhs = Expression(18, Sub), rhs = Counter(5) - expression 9 operands: lhs = Counter(16), rhs = Counter(4) -- expression 10 operands: lhs = Expression(19, Sub), rhs = Zero -- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 12 operands: lhs = Counter(16), rhs = Counter(4) -- expression 13 operands: lhs = Expression(19, Sub), rhs = Counter(6) -- expression 14 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 15 operands: lhs = Counter(16), rhs = Counter(4) -- expression 16 operands: lhs = Expression(17, Sub), rhs = Zero -- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(7) -- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(6) -- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 20 operands: lhs = Counter(16), rhs = Counter(4) -- expression 21 operands: lhs = Expression(26, Sub), rhs = Counter(9) -- expression 22 operands: lhs = Counter(18), rhs = Counter(8) +- expression 10 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 11 operands: lhs = Counter(16), rhs = Counter(4) +- expression 12 operands: lhs = Expression(17, Sub), rhs = Counter(6) +- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 14 operands: lhs = Counter(16), rhs = Counter(4) +- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(7) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(6) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 18 operands: lhs = Counter(16), rhs = Counter(4) +- expression 19 operands: lhs = Expression(23, Sub), rhs = Counter(9) +- expression 20 operands: lhs = Counter(18), rhs = Counter(8) +- expression 21 operands: lhs = Counter(18), rhs = Counter(8) +- expression 22 operands: lhs = Expression(23, Sub), rhs = Counter(9) - expression 23 operands: lhs = Counter(18), rhs = Counter(8) -- expression 24 operands: lhs = Expression(25, Sub), rhs = Zero -- expression 25 operands: lhs = Expression(26, Sub), rhs = Counter(9) -- expression 26 operands: lhs = Counter(18), rhs = Counter(8) -- expression 27 operands: lhs = Expression(38, Sub), rhs = Counter(11) -- expression 28 operands: lhs = Expression(39, Sub), rhs = Counter(10) -- expression 29 operands: lhs = Expression(40, Sub), rhs = Counter(16) -- expression 30 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 31 operands: lhs = Expression(40, Sub), rhs = Counter(16) +- expression 24 operands: lhs = Expression(34, Sub), rhs = Counter(11) +- expression 25 operands: lhs = Expression(35, Sub), rhs = Counter(10) +- expression 26 operands: lhs = Expression(36, Sub), rhs = Counter(16) +- expression 27 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 28 operands: lhs = Expression(36, Sub), rhs = Counter(16) +- expression 29 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 30 operands: lhs = Expression(35, Sub), rhs = Counter(10) +- expression 31 operands: lhs = Expression(36, Sub), rhs = Counter(16) - expression 32 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 33 operands: lhs = Expression(39, Sub), rhs = Counter(10) -- expression 34 operands: lhs = Expression(40, Sub), rhs = Counter(16) -- expression 35 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 36 operands: lhs = Expression(37, Sub), rhs = Zero -- expression 37 operands: lhs = Expression(38, Sub), rhs = Counter(11) -- expression 38 operands: lhs = Expression(39, Sub), rhs = Counter(10) -- expression 39 operands: lhs = Expression(40, Sub), rhs = Counter(16) -- expression 40 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 41 operands: lhs = Expression(46, Sub), rhs = Counter(13) -- expression 42 operands: lhs = Counter(17), rhs = Counter(12) -- expression 43 operands: lhs = Counter(17), rhs = Counter(12) -- expression 44 operands: lhs = Expression(45, Sub), rhs = Zero -- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(13) -- expression 46 operands: lhs = Counter(17), rhs = Counter(12) -- expression 47 operands: lhs = Expression(52, Sub), rhs = Counter(15) -- expression 48 operands: lhs = Counter(19), rhs = Counter(14) -- expression 49 operands: lhs = Counter(19), rhs = Counter(14) -- expression 50 operands: lhs = Expression(51, Sub), rhs = Zero -- expression 51 operands: lhs = Expression(52, Sub), rhs = Counter(15) -- expression 52 operands: lhs = Counter(19), rhs = Counter(14) -- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(3) -- expression 54 operands: lhs = Counter(4), rhs = Expression(55, Add) -- expression 55 operands: lhs = Expression(56, Add), rhs = Expression(60, Add) -- expression 56 operands: lhs = Counter(5), rhs = Expression(57, Add) -- expression 57 operands: lhs = Expression(58, Add), rhs = Expression(59, Add) -- expression 58 operands: lhs = Counter(6), rhs = Counter(7) -- expression 59 operands: lhs = Counter(8), rhs = Counter(9) -- expression 60 operands: lhs = Expression(61, Add), rhs = Expression(62, Add) -- expression 61 operands: lhs = Counter(10), rhs = Counter(11) -- expression 62 operands: lhs = Expression(63, Add), rhs = Expression(64, Add) -- expression 63 operands: lhs = Counter(12), rhs = Counter(13) -- expression 64 operands: lhs = Counter(14), rhs = Counter(15) +- expression 33 operands: lhs = Expression(34, Sub), rhs = Counter(11) +- expression 34 operands: lhs = Expression(35, Sub), rhs = Counter(10) +- expression 35 operands: lhs = Expression(36, Sub), rhs = Counter(16) +- expression 36 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 37 operands: lhs = Expression(41, Sub), rhs = Counter(13) +- expression 38 operands: lhs = Counter(17), rhs = Counter(12) +- expression 39 operands: lhs = Counter(17), rhs = Counter(12) +- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(13) +- expression 41 operands: lhs = Counter(17), rhs = Counter(12) +- expression 42 operands: lhs = Expression(46, Sub), rhs = Counter(15) +- expression 43 operands: lhs = Counter(19), rhs = Counter(14) +- expression 44 operands: lhs = Counter(19), rhs = Counter(14) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(15) +- expression 46 operands: lhs = Counter(19), rhs = Counter(14) +- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3) +- expression 48 operands: lhs = Counter(4), rhs = Expression(49, Add) +- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(54, Add) +- expression 50 operands: lhs = Counter(5), rhs = Expression(51, Add) +- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 52 operands: lhs = Counter(6), rhs = Counter(7) +- expression 53 operands: lhs = Counter(8), rhs = Counter(9) +- expression 54 operands: lhs = Expression(55, Add), rhs = Expression(56, Add) +- expression 55 operands: lhs = Counter(10), rhs = Counter(11) +- expression 56 operands: lhs = Expression(57, Add), rhs = Expression(58, Add) +- expression 57 operands: lhs = Counter(12), rhs = Counter(13) +- expression 58 operands: lhs = Counter(14), rhs = Counter(15) Number of file 0 mappings: 40 - Code(Counter(0)) at (prev + 60, 1) to (start + 3, 23) - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) = (c0 + (c1 + c2)) -- Code(Expression(40, Sub)) at (prev + 2, 9) to (start + 4, 26) +- Code(Expression(36, Sub)) at (prev + 2, 9) to (start + 4, 26) = ((c0 + (c1 + c2)) - c3) - Code(Counter(16)) at (prev + 6, 13) to (start + 0, 47) - Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(20, Sub)) at (prev + 0, 49) to (start + 3, 53) +- Code(Expression(18, Sub)) at (prev + 0, 49) to (start + 3, 53) = (c16 - c4) - Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18) -- Code(Expression(19, Sub)) at (prev + 2, 17) to (start + 4, 18) +- Code(Expression(17, Sub)) at (prev + 2, 17) to (start + 4, 18) = ((c16 - c4) - c5) -- Code(Expression(17, Sub)) at (prev + 5, 17) to (start + 0, 20) +- Code(Expression(15, Sub)) at (prev + 5, 17) to (start + 0, 20) = ((((c16 - c4) - c5) - c6) - c7) -- Code(Expression(10, Add)) at (prev + 0, 23) to (start + 0, 65) - = (((c16 - c4) - c5) + Zero) +- Code(Expression(17, Sub)) at (prev + 0, 23) to (start + 0, 65) + = ((c16 - c4) - c5) - Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 95) +- Code(Expression(16, Sub)) at (prev + 0, 67) to (start + 0, 95) = (((c16 - c4) - c5) - c6) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) -- Code(Expression(16, Add)) at (prev + 1, 13) to (start + 0, 32) - = (((((c16 - c4) - c5) - c6) - c7) + Zero) -- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(15, Sub)) at (prev + 1, 13) to (start + 0, 32) + = ((((c16 - c4) - c5) - c6) - c7) +- Code(Expression(22, Sub)) at (prev + 1, 17) to (start + 0, 20) = ((c18 - c8) - c9) - Code(Counter(18)) at (prev + 0, 23) to (start + 0, 65) - Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(26, Sub)) at (prev + 0, 67) to (start + 0, 96) +- Code(Expression(23, Sub)) at (prev + 0, 67) to (start + 0, 96) = (c18 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) -- Code(Expression(24, Add)) at (prev + 1, 13) to (start + 0, 32) - = (((c18 - c8) - c9) + Zero) -- Code(Expression(37, Sub)) at (prev + 4, 17) to (start + 0, 20) +- Code(Expression(22, Sub)) at (prev + 1, 13) to (start + 0, 32) + = ((c18 - c8) - c9) +- Code(Expression(33, Sub)) at (prev + 4, 17) to (start + 0, 20) = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) -- Code(Expression(39, Sub)) at (prev + 0, 23) to (start + 0, 66) +- Code(Expression(35, Sub)) at (prev + 0, 23) to (start + 0, 66) = (((c0 + (c1 + c2)) - c3) - c16) - Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67) -- Code(Expression(38, Sub)) at (prev + 0, 68) to (start + 0, 97) +- Code(Expression(34, Sub)) at (prev + 0, 68) to (start + 0, 97) = ((((c0 + (c1 + c2)) - c3) - c16) - c10) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) -- Code(Expression(36, Add)) at (prev + 1, 13) to (start + 0, 32) - = ((((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) + Zero) -- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32) + = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) +- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 20) = ((c17 - c12) - c13) - Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54) - Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55) -- Code(Expression(46, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(41, Sub)) at (prev + 1, 18) to (start + 0, 47) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(44, Add)) at (prev + 1, 13) to (start + 0, 32) - = (((c17 - c12) - c13) + Zero) -- Code(Expression(51, Sub)) at (prev + 1, 17) to (start + 0, 20) +- Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 32) + = ((c17 - c12) - c13) +- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20) = ((c19 - c14) - c15) - Code(Counter(19)) at (prev + 0, 23) to (start + 1, 54) - Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18) -- Code(Expression(52, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(46, Sub)) at (prev + 1, 18) to (start + 0, 47) = (c19 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) -- Code(Expression(50, Add)) at (prev + 2, 13) to (start + 0, 32) - = (((c19 - c14) - c15) + Zero) +- Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 32) + = ((c19 - c14) - c15) - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) -- Code(Expression(53, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c4 + ((c5 + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15))))) + c3) diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/status-quo/unused.cov-map index c8b8f195fbd5b..9383d1e90ac20 100644 --- a/tests/coverage-map/status-quo/unused.cov-map +++ b/tests/coverage-map/status-quo/unused.cov-map @@ -47,45 +47,45 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2) Function name: unused::unused_func (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14) +- Code(Zero) at (prev + 19, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_func2 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 25, 1) to (start + 1, 14) +- Code(Zero) at (prev + 25, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_func3 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 14) +- Code(Zero) at (prev + 31, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_template_func::<_> (unused) -Raw bytes (34): 0x[01, 01, 00, 06, 01, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 00, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 18) +- Code(Zero) at (prev + 11, 1) to (start + 1, 18) - Code(Zero) at (prev + 2, 11) to (start + 0, 17) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) - Code(Zero) at (prev + 0, 19) to (start + 0, 25) diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage-map/status-quo/yield.cov-map index 16caa2db343bb..c9c9709fa4f30 100644 --- a/tests/coverage-map/status-quo/yield.cov-map +++ b/tests/coverage-map/status-quo/yield.cov-map @@ -1,54 +1,44 @@ Function name: yield::main -Raw bytes (118): 0x[01, 01, 11, 01, 00, 05, 09, 0d, 00, 0d, 11, 32, 15, 0d, 11, 11, 15, 2e, 00, 32, 15, 0d, 11, 2e, 00, 32, 15, 0d, 11, 19, 1d, 21, 00, 25, 29, 2d, 00, 10, 01, 07, 01, 01, 16, 03, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 07, 01, 0e, 00, 34, 0b, 02, 0b, 00, 2e, 32, 01, 22, 00, 27, 2e, 00, 2c, 00, 2e, 1b, 01, 0e, 00, 34, 1f, 03, 09, 00, 16, 2b, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 37, 01, 0e, 00, 34, 3b, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 3f, 01, 0e, 00, 34, 43, 02, 01, 00, 02] +Raw bytes (106): 0x[01, 01, 0b, 05, 09, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 17 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(1), rhs = Counter(2) -- expression 2 operands: lhs = Counter(3), rhs = Zero +Number of expressions: 11 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(3), rhs = Counter(4) +- expression 2 operands: lhs = Expression(8, Sub), rhs = Counter(5) - expression 3 operands: lhs = Counter(3), rhs = Counter(4) -- expression 4 operands: lhs = Expression(12, Sub), rhs = Counter(5) -- expression 5 operands: lhs = Counter(3), rhs = Counter(4) -- expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Expression(11, Sub), rhs = Zero -- expression 8 operands: lhs = Expression(12, Sub), rhs = Counter(5) -- expression 9 operands: lhs = Counter(3), rhs = Counter(4) -- expression 10 operands: lhs = Expression(11, Sub), rhs = Zero -- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(5) -- expression 12 operands: lhs = Counter(3), rhs = Counter(4) -- expression 13 operands: lhs = Counter(6), rhs = Counter(7) -- expression 14 operands: lhs = Counter(8), rhs = Zero -- expression 15 operands: lhs = Counter(9), rhs = Counter(10) -- expression 16 operands: lhs = Counter(11), rhs = Zero +- expression 4 operands: lhs = Counter(4), rhs = Counter(5) +- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(5) +- expression 6 operands: lhs = Counter(3), rhs = Counter(4) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(5) +- expression 8 operands: lhs = Counter(3), rhs = Counter(4) +- expression 9 operands: lhs = Counter(6), rhs = Counter(7) +- expression 10 operands: lhs = Counter(9), rhs = Counter(10) Number of file 0 mappings: 16 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) -- Code(Expression(0, Add)) at (prev + 6, 11) to (start + 0, 46) - = (c0 + Zero) +- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 52) = (c1 + c2) -- Code(Expression(2, Add)) at (prev + 2, 11) to (start + 0, 46) - = (c3 + Zero) -- Code(Expression(12, Sub)) at (prev + 1, 34) to (start + 0, 39) +- Code(Counter(3)) at (prev + 2, 11) to (start + 0, 46) +- Code(Expression(8, Sub)) at (prev + 1, 34) to (start + 0, 39) = (c3 - c4) -- Code(Expression(11, Sub)) at (prev + 0, 44) to (start + 0, 46) +- Code(Expression(7, Sub)) at (prev + 0, 44) to (start + 0, 46) = ((c3 - c4) - c5) -- Code(Expression(6, Add)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(4, Add)) at (prev + 1, 14) to (start + 0, 52) = (c4 + c5) -- Code(Expression(7, Add)) at (prev + 3, 9) to (start + 0, 22) - = (((c3 - c4) - c5) + Zero) -- Code(Expression(10, Add)) at (prev + 7, 11) to (start + 0, 46) - = (((c3 - c4) - c5) + Zero) +- Code(Expression(7, Sub)) at (prev + 3, 9) to (start + 0, 22) + = ((c3 - c4) - c5) +- Code(Expression(7, Sub)) at (prev + 7, 11) to (start + 0, 46) + = ((c3 - c4) - c5) - Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(13, Add)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(9, Add)) at (prev + 1, 14) to (start + 0, 52) = (c6 + c7) -- Code(Expression(14, Add)) at (prev + 2, 11) to (start + 0, 46) - = (c8 + Zero) +- Code(Counter(8)) at (prev + 2, 11) to (start + 0, 46) - Code(Counter(11)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(15, Add)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(10, Add)) at (prev + 1, 14) to (start + 0, 52) = (c9 + c10) -- Code(Expression(16, Add)) at (prev + 2, 1) to (start + 0, 2) - = (c11 + Zero) +- Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) Function name: yield::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06] diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage-map/unreachable.cov-map new file mode 100644 index 0000000000000..495419820c1f5 --- /dev/null +++ b/tests/coverage-map/unreachable.cov-map @@ -0,0 +1,24 @@ +Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 49] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 73) + +Function name: unreachable::unreachable_function +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 1) to (start + 2, 2) + +Function name: unreachable::unreachable_intrinsic +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2) + diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage-map/unreachable.rs new file mode 100644 index 0000000000000..6385bfa160d7d --- /dev/null +++ b/tests/coverage-map/unreachable.rs @@ -0,0 +1,37 @@ +#![feature(core_intrinsics)] +#![feature(coverage_attribute)] +// compile-flags: --edition=2021 + +// +// If we instrument a function for coverage, but all of its counter-increment +// statements are removed by MIR optimizations, LLVM will think it isn't +// instrumented and it will disappear from coverage maps and coverage reports. +// Most MIR opts won't cause this because they tend not to remove statements +// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends +// with `TerminatorKind::Unreachable`. + +use std::hint::{black_box, unreachable_unchecked}; + +static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; + +fn unreachable_function() { + unsafe { unreachable_unchecked() } +} + +// Use an intrinsic to more reliably trigger unreachable-propagation. +fn unreachable_intrinsic() { + unsafe { std::intrinsics::unreachable() } +} + +#[coverage(off)] +fn main() { + if black_box(false) { + UNREACHABLE_CLOSURE(); + } + if black_box(false) { + unreachable_function(); + } + if black_box(false) { + unreachable_intrinsic(); + } +} diff --git a/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs index f518266016e09..b9f74340472c0 100644 --- a/tests/incremental/change_crate_dep_kind.rs +++ b/tests/incremental/change_crate_dep_kind.rs @@ -5,6 +5,7 @@ // needs-unwind // revisions:cfail1 cfail2 // compile-flags: -Z query-dep-graph -Cpanic=unwind +// needs-unwind // build-pass (FIXME(62277): could be check-pass?) #![feature(panic_unwind)] diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs index 193e792c84330..98c762e409787 100644 --- a/tests/incremental/hashes/for_loops.rs +++ b/tests/incremental/hashes/for_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -180,7 +180,7 @@ pub fn add_loop_label_to_break() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 182ca7d926c6b..23b81705f9aa0 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -302,7 +302,7 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] diff --git a/tests/incremental/hashes/loop_expressions.rs b/tests/incremental/hashes/loop_expressions.rs index 87b86479d07bd..13e37bd59f8e8 100644 --- a/tests/incremental/hashes/loop_expressions.rs +++ b/tests/incremental/hashes/loop_expressions.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; diff --git a/tests/incremental/hashes/while_loops.rs b/tests/incremental/hashes/while_loops.rs index c1cc0b62bc244..077d76fdd43a1 100644 --- a/tests/incremental/hashes/while_loops.rs +++ b/tests/incremental/hashes/while_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_loop_condition() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; @@ -211,7 +211,7 @@ pub fn change_continue_label() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir index 9be5b8509c728..98b1befc3bfa2 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir @@ -9,7 +9,7 @@ storage_conflicts: BitMatrix(0x0) {}, } */ -fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]>, _2: &mut Context<'_>) -> Poll<()> { +fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _4; let mut _0: std::task::Poll<()>; let mut _3: (); @@ -17,23 +17,31 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]> let mut _5: u32; bb0: { - _5 = discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))); - switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; + _5 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}))); + switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5]; } bb1: { _4 = move _2; _3 = const (); - _0 = Poll::<()>::Ready(move _3); - discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; - return; + goto -> bb3; } bb2: { - assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind unreachable]; + _0 = Poll::<()>::Ready(move _3); + discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}))) = 1; + return; } bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind unreachable]; + } + + bb5: { unreachable; } } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index b06666c9dd771..15330b13cc214 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -2,13 +2,16 @@ /* generator_layout = GeneratorLayout { field_tys: { _0: GeneratorSavedTy { - ty: Alias( - Opaque, - AliasTy { - args: [ - ], - def_id: DefId(0:7 ~ async_await[ccf8]::a::{opaque#0}), - }, + ty: Generator( + DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + [ + std::future::ResumeTy, + (), + (), + GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), + (), + ], + Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:15:9: 15:14 (#8), @@ -17,13 +20,16 @@ ignore_for_traits: false, }, _1: GeneratorSavedTy { - ty: Alias( - Opaque, - AliasTy { - args: [ - ], - def_id: DefId(0:7 ~ async_await[ccf8]::a::{opaque#0}), - }, + ty: Generator( + DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + [ + std::future::ResumeTy, + (), + (), + GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), + (), + ], + Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:16:9: 16:14 (#10), @@ -45,19 +51,19 @@ }, } */ -fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, _2: &mut Context<'_>) -> Poll<()> { +fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _38; let mut _0: std::task::Poll<()>; let _3: (); - let mut _4: impl std::future::Future; - let mut _5: impl std::future::Future; - let mut _6: impl std::future::Future; + let mut _4: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _5: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _6: {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _7: (); let _8: (); let mut _9: std::task::Poll<()>; - let mut _10: std::pin::Pin<&mut impl std::future::Future>; - let mut _11: &mut impl std::future::Future; - let mut _12: &mut impl std::future::Future; + let mut _10: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>; + let mut _11: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _12: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _13: &mut std::task::Context<'_>; let mut _14: &mut std::task::Context<'_>; let mut _15: &mut std::task::Context<'_>; @@ -65,14 +71,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, let mut _18: !; let mut _19: &mut std::task::Context<'_>; let mut _20: (); - let mut _21: impl std::future::Future; - let mut _22: impl std::future::Future; - let mut _23: impl std::future::Future; + let mut _21: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _22: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _23: {async fn body@$DIR/async_await.rs:11:14: 11:16}; let _24: (); let mut _25: std::task::Poll<()>; - let mut _26: std::pin::Pin<&mut impl std::future::Future>; - let mut _27: &mut impl std::future::Future; - let mut _28: &mut impl std::future::Future; + let mut _26: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>; + let mut _27: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _28: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _29: &mut std::task::Context<'_>; let mut _30: &mut std::task::Context<'_>; let mut _31: &mut std::task::Context<'_>; @@ -84,7 +90,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, let mut _38: &mut std::task::Context<'_>; let mut _39: u32; scope 1 { - debug __awaitee => (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future); + debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); let _17: (); scope 2 { } @@ -93,7 +99,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } } scope 4 { - debug __awaitee => (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future); + debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); let _33: (); scope 5 { } @@ -103,8 +109,8 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } bb0: { - _39 = discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))); - switchInt(move _39) -> [0: bb1, 1: bb28, 3: bb26, 4: bb27, otherwise: bb29]; + _39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2}))); + switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb30]; } bb1: { @@ -116,13 +122,13 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } bb2: { - _4 = as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; + _4 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; } bb3: { StorageDead(_5); nop; - (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future) = move _4; + (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}) = move _4; goto -> bb4; } @@ -132,9 +138,9 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future); + _12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); _11 = &mut (*_12); - _10 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; + _10 = Pin::<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; } bb5: { @@ -150,7 +156,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, bb6: { _13 = &mut (*_14); StorageDead(_15); - _9 = as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; + _9 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; } bb7: { @@ -170,7 +176,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_20); _20 = (); _0 = Poll::<()>::Pending; - discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; + discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2}))) = 3; return; } @@ -187,7 +193,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageDead(_12); StorageDead(_9); StorageDead(_8); - goto -> bb12; + drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16})) -> [return: bb12, unwind unreachable]; } bb11: { @@ -212,13 +218,13 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } bb14: { - _21 = as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + _21 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; } bb15: { StorageDead(_22); nop; - (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future) = move _21; + (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}) = move _21; goto -> bb16; } @@ -228,9 +234,9 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future); + _28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); _27 = &mut (*_28); - _26 = Pin::<&mut impl Future>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; + _26 = Pin::<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; } bb17: { @@ -246,7 +252,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, bb18: { _29 = &mut (*_30); StorageDead(_31); - _25 = as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; + _25 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; } bb19: { @@ -266,7 +272,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_36); _36 = (); _0 = Poll::<()>::Pending; - discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; + discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2}))) = 4; return; } @@ -279,7 +285,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageDead(_28); StorageDead(_25); StorageDead(_24); - goto -> bb23; + drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16})) -> [return: bb23, unwind unreachable]; } bb22: { @@ -297,16 +303,20 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, bb24: { StorageDead(_21); - goto -> bb25; + goto -> bb26; } bb25: { _0 = Poll::<()>::Ready(move _37); - discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; + discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2}))) = 1; return; } bb26: { + goto -> bb25; + } + + bb27: { StorageLive(_3); StorageLive(_4); StorageLive(_19); @@ -315,7 +325,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, goto -> bb11; } - bb27: { + bb28: { StorageLive(_21); StorageLive(_35); StorageLive(_36); @@ -323,11 +333,11 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, goto -> bb22; } - bb28: { - assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind unreachable]; + bb29: { + assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; } - bb29: { + bb30: { unreachable; } } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff index 7ba51ccdbf6d4..d585ae89e8296 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; + _4 = const (0_u8, true); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 545b7f22f6e0c..9fe3909063809 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = const (0_u8, true); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff new file mode 100644 index 0000000000000..b9b46f16a8b7d --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff @@ -0,0 +1,119 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); +- _7 = AlignOf([bool; 0]); +- _6 = _7 as *mut [bool; 0] (Transmute); ++ _7 = const 1_usize; ++ _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); +- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); +- _5 = NonNull::<[bool; 0]> { pointer: _8 }; ++ _8 = const {0x1 as *const [bool; 0]}; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); +- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); +- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); +- _2 = Box::<[bool]>(_3, const std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); +- _1 = A { foo: move _2 }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_1); + return; + } ++ } ++ ++ alloc11 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ ++ } ++ ++ alloc10 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ ++ } ++ ++ alloc7 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff new file mode 100644 index 0000000000000..93b18f23e61a8 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff @@ -0,0 +1,123 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); +- _7 = AlignOf([bool; 0]); +- _6 = _7 as *mut [bool; 0] (Transmute); ++ _7 = const 1_usize; ++ _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); +- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); +- _5 = NonNull::<[bool; 0]> { pointer: _8 }; ++ _8 = const {0x1 as *const [bool; 0]}; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); +- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); +- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); +- _2 = Box::<[bool]>(_3, const std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); +- _1 = A { foo: move _2 }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } ++ } ++ ++ alloc11 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ ++ } ++ ++ alloc10 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ ++ } ++ ++ alloc7 (size: 8, align: 4) { ++ 01 00 00 00 00 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff new file mode 100644 index 0000000000000..3d3af62856bdd --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff @@ -0,0 +1,119 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); +- _7 = AlignOf([bool; 0]); +- _6 = _7 as *mut [bool; 0] (Transmute); ++ _7 = const 1_usize; ++ _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); +- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); +- _5 = NonNull::<[bool; 0]> { pointer: _8 }; ++ _8 = const {0x1 as *const [bool; 0]}; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); +- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); +- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); +- _2 = Box::<[bool]>(_3, const std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); +- _1 = A { foo: move _2 }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_1); + return; + } ++ } ++ ++ alloc11 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ alloc10 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ alloc7 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff new file mode 100644 index 0000000000000..1933f9bafb369 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff @@ -0,0 +1,123 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); +- _7 = AlignOf([bool; 0]); +- _6 = _7 as *mut [bool; 0] (Transmute); ++ _7 = const 1_usize; ++ _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); +- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); +- _5 = NonNull::<[bool; 0]> { pointer: _8 }; ++ _8 = const {0x1 as *const [bool; 0]}; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); +- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); +- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); +- _2 = Box::<[bool]>(_3, const std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); +- _1 = A { foo: move _2 }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } ++ } ++ ++ alloc11 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ alloc10 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ alloc7 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff new file mode 100644 index 0000000000000..7862c23da809f --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -0,0 +1,111 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _8 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_1); + return; + } + } + + alloc11 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + + alloc10 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + + alloc7 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff new file mode 100644 index 0000000000000..bd4150ebb4520 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -0,0 +1,115 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _8 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + } + + alloc11 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + + alloc10 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + + alloc7 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff new file mode 100644 index 0000000000000..312fc7b7a82b5 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -0,0 +1,111 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _8 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_1); + return; + } + } + + alloc11 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + + alloc10 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + + alloc7 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff new file mode 100644 index 0000000000000..3227d8b84353a --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -0,0 +1,115 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: A; + let mut _2: std::boxed::Box<[bool]>; + scope 1 { + debug a => _1; + } + scope 2 (inlined as Default>::default) { + let _3: std::ptr::Unique<[bool]>; + let mut _4: std::ptr::Unique<[bool; 0]>; + scope 3 { + debug ptr => _3; + } + scope 4 (inlined Unique::<[bool; 0]>::dangling) { + let mut _5: std::ptr::NonNull<[bool; 0]>; + scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let mut _7: usize; + scope 6 { + let _6: *mut [bool; 0]; + scope 7 { + debug ptr => _6; + scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { + debug ptr => _6; + let mut _8: *const [bool; 0]; + scope 12 { + scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { + debug ptr => _6; + scope 14 (inlined ptr::mut_ptr::::is_null) { + debug self => _6; + let mut _9: *mut u8; + scope 15 { + scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + debug ptr => _9; + scope 17 (inlined ptr::mut_ptr::::addr) { + debug self => _9; + scope 18 { + scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + debug self => _9; + } + } + } + } + } + } + } + } + } + } + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined invalid_mut::<[bool; 0]>) { + debug addr => _7; + scope 10 { + } + } + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _8 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + StorageDead(_9); + StorageDead(_8); + StorageDead(_6); + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + StorageDead(_5); + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + StorageDead(_4); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + StorageDead(_3); + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + } + + alloc11 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + + alloc10 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + + alloc7 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs new file mode 100644 index 0000000000000..dfeccd3eb94ee --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -0,0 +1,17 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zmir-enable-passes=+ConstProp,+Inline +// ignore-debug assertions change the output MIR +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +struct A { + foo: Box<[bool]>, +} + +// EMIT_MIR default_boxed_slice.main.ConstProp.diff +// EMIT_MIR default_boxed_slice.main.DataflowConstProp.diff +fn main() { + // ConstProp will create a constant of type `Box<[bool]>`. + // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. + let a: A = A { foo: Box::default() }; +} diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 9a68d3b51b561..87bb1454c9624 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; + _4 = CheckedAdd(const u8::MAX, const 1_u8); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index c1d281ab788f0..b2f13640a4c05 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = CheckedAdd(const u8::MAX, const 1_u8); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff new file mode 100644 index 0000000000000..cf73358dc52eb --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff @@ -0,0 +1,29 @@ +- // MIR for `cycle` before DeadStoreElimination ++ // MIR for `cycle` after DeadStoreElimination + + fn cycle(_1: i32, _2: i32, _3: i32) -> () { + let mut _0: (); + let mut _4: bool; +- let mut _5: i32; + + bb0: { + _4 = cond() -> [return: bb1, unwind continue]; + } + + bb1: { + switchInt(_4) -> [1: bb2, otherwise: bb3]; + } + + bb2: { +- _5 = _3; +- _3 = _2; +- _2 = _1; +- _1 = _5; + _4 = cond() -> [return: bb1, unwind continue]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-abort.diff deleted file mode 100644 index 6221d478041a2..0000000000000 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-abort.diff +++ /dev/null @@ -1,73 +0,0 @@ -- // MIR for `cycle` before DeadStoreElimination -+ // MIR for `cycle` after DeadStoreElimination - - fn cycle(_1: i32, _2: i32, _3: i32) -> () { - debug x => _1; - debug y => _2; - debug z => _3; - let mut _0: (); -- let mut _4: (); -- let mut _5: bool; -- let _6: i32; -- let mut _7: i32; -- let mut _8: i32; -- let mut _9: i32; -- let mut _10: !; -- let _11: (); -- let mut _12: !; -+ let mut _4: bool; -+ let _5: i32; - scope 1 { -- debug temp => _6; -+ debug temp => _5; - } - - bb0: { - goto -> bb1; - } - - bb1: { -- StorageLive(_5); -- _5 = cond() -> [return: bb2, unwind unreachable]; -+ StorageLive(_4); -+ _4 = cond() -> [return: bb2, unwind unreachable]; - } - - bb2: { -- switchInt(move _5) -> [0: bb4, otherwise: bb3]; -+ switchInt(move _4) -> [0: bb4, otherwise: bb3]; - } - - bb3: { -- StorageLive(_6); -- _6 = _3; -- StorageLive(_7); -- _7 = _2; -- _3 = move _7; -- StorageDead(_7); -- StorageLive(_8); -- _8 = _1; -- _2 = move _8; -- StorageDead(_8); -- StorageLive(_9); -- _9 = _6; -- _1 = move _9; -- StorageDead(_9); -- _4 = const (); -- StorageDead(_6); -+ StorageLive(_5); - StorageDead(_5); -+ StorageDead(_4); - goto -> bb1; - } - - bb4: { -- StorageLive(_11); - _0 = const (); -- StorageDead(_11); -- StorageDead(_5); -+ StorageDead(_4); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff deleted file mode 100644 index 4b922e05e105b..0000000000000 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff +++ /dev/null @@ -1,73 +0,0 @@ -- // MIR for `cycle` before DeadStoreElimination -+ // MIR for `cycle` after DeadStoreElimination - - fn cycle(_1: i32, _2: i32, _3: i32) -> () { - debug x => _1; - debug y => _2; - debug z => _3; - let mut _0: (); -- let mut _4: (); -- let mut _5: bool; -- let _6: i32; -- let mut _7: i32; -- let mut _8: i32; -- let mut _9: i32; -- let mut _10: !; -- let _11: (); -- let mut _12: !; -+ let mut _4: bool; -+ let _5: i32; - scope 1 { -- debug temp => _6; -+ debug temp => _5; - } - - bb0: { - goto -> bb1; - } - - bb1: { -- StorageLive(_5); -- _5 = cond() -> [return: bb2, unwind continue]; -+ StorageLive(_4); -+ _4 = cond() -> [return: bb2, unwind continue]; - } - - bb2: { -- switchInt(move _5) -> [0: bb4, otherwise: bb3]; -+ switchInt(move _4) -> [0: bb4, otherwise: bb3]; - } - - bb3: { -- StorageLive(_6); -- _6 = _3; -- StorageLive(_7); -- _7 = _2; -- _3 = move _7; -- StorageDead(_7); -- StorageLive(_8); -- _8 = _1; -- _2 = move _8; -- StorageDead(_8); -- StorageLive(_9); -- _9 = _6; -- _1 = move _9; -- StorageDead(_9); -- _4 = const (); -- StorageDead(_6); -+ StorageLive(_5); - StorageDead(_5); -+ StorageDead(_4); - goto -> bb1; - } - - bb4: { -- StorageLive(_11); - _0 = const (); -- StorageDead(_11); -- StorageDead(_5); -+ StorageDead(_4); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index cd34fe96e8c64..e3def2f65da17 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -1,21 +1,40 @@ -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// This example is interesting because the non-transitive version of `MaybeLiveLocals` would +// report that *all* of these stores are live. +// +// needs-unwind // unit-test: DeadStoreElimination +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + #[inline(never)] fn cond() -> bool { false } // EMIT_MIR cycle.cycle.DeadStoreElimination.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn cycle(mut x: i32, mut y: i32, mut z: i32) { - // This example is interesting because the non-transitive version of `MaybeLiveLocals` would - // report that *all* of these stores are live. - while cond() { - let temp = z; - z = y; - y = x; - x = temp; - } + // We use custom MIR to avoid generating debuginfo, that would force to preserve writes. + mir!( + let condition: bool; + { + Call(condition = cond(), bb1) + } + bb1 = { + match condition { true => bb2, _ => ret } + } + bb2 = { + let temp = z; + z = y; + y = x; + x = temp; + Call(condition = cond(), bb1) + } + ret = { + Return() + } + ) } fn main() { diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir index a3ec090107514..eb160fc194a81 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir @@ -7,15 +7,16 @@ fn f(_1: usize) -> usize { let mut _3: usize; let mut _4: usize; scope 1 { - debug b => _1; + debug b => _3; } bb0: { nop; + _3 = _1; + _1 = const 5_usize; nop; nop; - nop; - nop; + _1 = move _3; nop; nop; nop; diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir index 185feb4b41816..9147de2ec473b 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir @@ -7,15 +7,16 @@ fn f(_1: usize) -> usize { let mut _3: usize; let mut _4: usize; scope 1 { - debug b => _1; + debug b => _3; } bb0: { nop; + _3 = _1; + _1 = const 5_usize; nop; nop; - nop; - nop; + _1 = move _3; nop; nop; nop; diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 459a9c442b3e9..d5e58265dcc8e 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -22,8 +22,10 @@ } bb1: { + _1 = Un { us: move _2 }; StorageDead(_2); StorageLive(_3); + _3 = (_1.0: u32); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index d2eef90582d54..5eaaeba135bd0 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -22,8 +22,10 @@ } bb1: { + _1 = Un { us: move _2 }; StorageDead(_2); StorageLive(_3); + _3 = (_1.0: u32); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir index 958078b97064e..d8bea14204d50 100644 --- a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir +++ b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir @@ -21,7 +21,7 @@ }, } */ -fn main::{closure#0}(_1: *mut [generator@$DIR/generator_drop_cleanup.rs:10:15: 10:17]) -> () { +fn main::{closure#0}(_1: *mut {generator@$DIR/generator_drop_cleanup.rs:10:15: 10:17}) -> () { let mut _0: (); let mut _2: (); let _3: std::string::String; diff --git a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir index 7e050e585b1db..d8b27eda8f2d8 100644 --- a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir +++ b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir @@ -21,7 +21,7 @@ }, } */ -fn main::{closure#0}(_1: *mut [generator@$DIR/generator_drop_cleanup.rs:10:15: 10:17]) -> () { +fn main::{closure#0}(_1: *mut {generator@$DIR/generator_drop_cleanup.rs:10:15: 10:17}) -> () { let mut _0: (); let mut _2: (); let _3: std::string::String; diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir index 25c656b3a7332..4587282de93a7 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: [generator@$DIR/generator_storage_dead_unwind.rs:22:16: 22:18], _2: ()) -> () +fn main::{closure#0}(_1: {generator@$DIR/generator_storage_dead_unwind.rs:22:16: 22:18}, _2: ()) -> () yields () { let mut _0: (); diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 6fcceb6c66bff..38026f65bbd1e 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: [generator@$DIR/generator_storage_dead_unwind.rs:22:16: 22:18], _2: ()) -> () +fn main::{closure#0}(_1: {generator@$DIR/generator_storage_dead_unwind.rs:22:16: 22:18}, _2: ()) -> () yields () { let mut _0: (); diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 13d703b908cc8..ac7549f93b121 100644 --- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -21,7 +21,7 @@ }, } */ -fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]>, _2: u8) -> GeneratorState<(), ()> { +fn main::{closure#0}(_1: Pin<&mut {generator@$DIR/generator_tiny.rs:19:16: 19:24}>, _2: u8) -> GeneratorState<(), ()> { debug _x => _10; let mut _0: std::ops::GeneratorState<(), ()>; let _3: HasDrop; @@ -34,18 +34,18 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24 let _10: u8; let mut _11: u32; scope 1 { - debug _d => (((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); + debug _d => (((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:19:16: 19:24})) as variant#3).0: HasDrop); } bb0: { - _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))); + _11 = discriminant((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:19:16: 19:24}))); switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6]; } bb1: { _10 = move _2; nop; - (((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop) = HasDrop; + (((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:19:16: 19:24})) as variant#3).0: HasDrop) = HasDrop; StorageLive(_4); goto -> bb2; } @@ -55,7 +55,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24 StorageLive(_7); _7 = (); _0 = GeneratorState::<(), ()>::Yielded(move _7); - discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; + discriminant((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:19:16: 19:24}))) = 3; return; } diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff new file mode 100644 index 0000000000000..3f5173c189e12 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff @@ -0,0 +1,342 @@ +- // MIR for `arithmetic` before GVN ++ // MIR for `arithmetic` after GVN + + fn arithmetic(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let _5: (); + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let _11: (); + let mut _12: u64; + let mut _13: u64; + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: bool; + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let _49: (); + let mut _50: u64; + let mut _51: u64; + let _52: (); + let mut _53: u64; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: u64; + let _58: (); + let mut _59: u64; + let mut _60: u64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0_u64); +- StorageDead(_4); ++ _3 = Add(_1, const 0_u64); + _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0_u64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0_u64); + _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0_u64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0_u64); + _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Mul(move _13, const 1_u64); +- StorageDead(_13); ++ _12 = Mul(_1, const 1_u64); + _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; + _17 = Eq(const 0_u64, const 0_u64); +- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind unreachable]; ++ assert(!_17, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind unreachable]; + } + + bb5: { +- _15 = Div(move _16, const 0_u64); +- StorageDead(_16); ++ _15 = Div(_1, const 0_u64); + _14 = opaque::(move _15) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 1_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind unreachable]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind unreachable]; + } + + bb7: { +- _19 = Div(move _20, const 1_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 1_u64); + _18 = opaque::(move _19) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; ++ _25 = Eq(_1, const 0_u64); ++ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _23 = Div(const 0_u64, move _24); +- StorageDead(_24); ++ _23 = Div(const 0_u64, _1); + _22 = opaque::(move _23) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; ++ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; + } + + bb11: { +- _27 = Div(const 1_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 1_u64, _1); + _26 = opaque::(move _27) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(const 0_u64, const 0_u64); +- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind unreachable]; ++ assert(!_17, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind unreachable]; + } + + bb13: { +- _31 = Rem(move _32, const 0_u64); +- StorageDead(_32); ++ _31 = Rem(_1, const 0_u64); + _30 = opaque::(move _31) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 1_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind unreachable]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind unreachable]; + } + + bb15: { +- _35 = Rem(move _36, const 1_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 1_u64); + _34 = opaque::(move _35) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(_40, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; + } + + bb17: { +- _39 = Rem(const 0_u64, move _40); +- StorageDead(_40); ++ _39 = Rem(const 0_u64, _1); + _38 = opaque::(move _39) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; + } + + bb19: { +- _43 = Rem(const 1_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 1_u64, _1); + _42 = opaque::(move _43) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = BitAnd(move _48, const 0_u64); +- StorageDead(_48); ++ _47 = BitAnd(_1, const 0_u64); + _46 = opaque::(move _47) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = BitOr(move _51, const 0_u64); +- StorageDead(_51); ++ _50 = BitOr(_1, const 0_u64); + _49 = opaque::(move _50) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); + StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = BitXor(move _54, const 0_u64); +- StorageDead(_54); ++ _53 = BitXor(_1, const 0_u64); + _52 = opaque::(move _53) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_53); + StorageDead(_52); + StorageLive(_55); + StorageLive(_56); +- StorageLive(_57); +- _57 = _1; +- _56 = Shr(move _57, const 0_i32); +- StorageDead(_57); ++ _56 = Shr(_1, const 0_i32); + _55 = opaque::(move _56) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_56); + StorageDead(_55); + StorageLive(_58); + StorageLive(_59); +- StorageLive(_60); +- _60 = _1; +- _59 = Shl(move _60, const 0_i32); +- StorageDead(_60); ++ _59 = Shl(_1, const 0_i32); + _58 = opaque::(move _59) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_59); + StorageDead(_58); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..38da21d91d41d --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff @@ -0,0 +1,342 @@ +- // MIR for `arithmetic` before GVN ++ // MIR for `arithmetic` after GVN + + fn arithmetic(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let _5: (); + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let _11: (); + let mut _12: u64; + let mut _13: u64; + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: bool; + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let _49: (); + let mut _50: u64; + let mut _51: u64; + let _52: (); + let mut _53: u64; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: u64; + let _58: (); + let mut _59: u64; + let mut _60: u64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0_u64); +- StorageDead(_4); ++ _3 = Add(_1, const 0_u64); + _2 = opaque::(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0_u64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0_u64); + _5 = opaque::(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0_u64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0_u64); + _8 = opaque::(move _9) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Mul(move _13, const 1_u64); +- StorageDead(_13); ++ _12 = Mul(_1, const 1_u64); + _11 = opaque::(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; + _17 = Eq(const 0_u64, const 0_u64); +- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind continue]; ++ assert(!_17, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind continue]; + } + + bb5: { +- _15 = Div(move _16, const 0_u64); +- StorageDead(_16); ++ _15 = Div(_1, const 0_u64); + _14 = opaque::(move _15) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 1_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind continue]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind continue]; + } + + bb7: { +- _19 = Div(move _20, const 1_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 1_u64); + _18 = opaque::(move _19) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; ++ _25 = Eq(_1, const 0_u64); ++ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; + } + + bb9: { +- _23 = Div(const 0_u64, move _24); +- StorageDead(_24); ++ _23 = Div(const 0_u64, _1); + _22 = opaque::(move _23) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; ++ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; + } + + bb11: { +- _27 = Div(const 1_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 1_u64, _1); + _26 = opaque::(move _27) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(const 0_u64, const 0_u64); +- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind continue]; ++ assert(!_17, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind continue]; + } + + bb13: { +- _31 = Rem(move _32, const 0_u64); +- StorageDead(_32); ++ _31 = Rem(_1, const 0_u64); + _30 = opaque::(move _31) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 1_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind continue]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind continue]; + } + + bb15: { +- _35 = Rem(move _36, const 1_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 1_u64); + _34 = opaque::(move _35) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(_40, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; + } + + bb17: { +- _39 = Rem(const 0_u64, move _40); +- StorageDead(_40); ++ _39 = Rem(const 0_u64, _1); + _38 = opaque::(move _39) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; + } + + bb19: { +- _43 = Rem(const 1_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 1_u64, _1); + _42 = opaque::(move _43) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = BitAnd(move _48, const 0_u64); +- StorageDead(_48); ++ _47 = BitAnd(_1, const 0_u64); + _46 = opaque::(move _47) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = BitOr(move _51, const 0_u64); +- StorageDead(_51); ++ _50 = BitOr(_1, const 0_u64); + _49 = opaque::(move _50) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); + StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = BitXor(move _54, const 0_u64); +- StorageDead(_54); ++ _53 = BitXor(_1, const 0_u64); + _52 = opaque::(move _53) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_53); + StorageDead(_52); + StorageLive(_55); + StorageLive(_56); +- StorageLive(_57); +- _57 = _1; +- _56 = Shr(move _57, const 0_i32); +- StorageDead(_57); ++ _56 = Shr(_1, const 0_i32); + _55 = opaque::(move _56) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_56); + StorageDead(_55); + StorageLive(_58); + StorageLive(_59); +- StorageLive(_60); +- _60 = _1; +- _59 = Shl(move _60, const 0_i32); +- StorageDead(_60); ++ _59 = Shl(_1, const 0_i32); + _58 = opaque::(move _59) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_59); + StorageDead(_58); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff new file mode 100644 index 0000000000000..0c342799e0794 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -0,0 +1,389 @@ +- // MIR for `arithmetic_checked` before GVN ++ // MIR for `arithmetic_checked` after GVN + + fn arithmetic_checked(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let mut _5: (u64, bool); + let _6: (); + let mut _7: u64; + let mut _8: u64; + let mut _9: (u64, bool); + let _10: (); + let mut _11: u64; + let mut _12: u64; + let mut _13: (u64, bool); + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: (u64, bool); + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let mut _49: bool; + let _50: (); + let mut _51: u64; + let mut _52: u64; + let _53: (); + let mut _54: u64; + let mut _55: u64; + let _56: (); + let mut _57: u64; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u32; + let mut _63: bool; + let _64: (); + let mut _65: u64; + let mut _66: u64; + let mut _67: u32; + let mut _68: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _5 = CheckedAdd(_4, const 0_u64); +- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable]; ++ _5 = CheckedAdd(_1, const 0_u64); ++ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _3 = move (_5.0: u64); +- StorageDead(_4); + _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_6); + StorageLive(_7); +- StorageLive(_8); +- _8 = _1; +- _9 = CheckedSub(_8, const 0_u64); +- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable]; ++ _9 = CheckedSub(_1, const 0_u64); ++ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; + } + + bb3: { + _7 = move (_9.0: u64); +- StorageDead(_8); + _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _13 = CheckedMul(_12, const 0_u64); +- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind unreachable]; ++ _13 = CheckedMul(_1, const 0_u64); ++ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind unreachable]; + } + + bb5: { + _11 = move (_13.0: u64); +- StorageDead(_12); + _10 = opaque::(move _11) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _17 = CheckedMul(_16, const 1_u64); +- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind unreachable]; ++ _17 = CheckedMul(_1, const 1_u64); ++ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind unreachable]; + } + + bb7: { + _15 = move (_17.0: u64); +- StorageDead(_16); + _14 = opaque::(move _15) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb9, unwind unreachable]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _19 = Div(move _20, const 0_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 0_u64); + _18 = opaque::(move _19) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; + _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb11, unwind unreachable]; ++ assert(!_25, "attempt to divide `{}` by zero", _1) -> [success: bb11, unwind unreachable]; + } + + bb11: { +- _23 = Div(move _24, const 1_u64); +- StorageDead(_24); ++ _23 = Div(_1, const 1_u64); + _22 = opaque::(move _23) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind unreachable]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind unreachable]; + } + + bb13: { +- _27 = Div(const 0_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 0_u64, _1); + _26 = opaque::(move _27) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind unreachable]; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind unreachable]; + } + + bb15: { +- _31 = Div(const 1_u64, move _32); +- StorageDead(_32); ++ _31 = Div(const 1_u64, _1); + _30 = opaque::(move _31) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb17, unwind unreachable]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb17, unwind unreachable]; + } + + bb17: { +- _35 = Rem(move _36, const 0_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 0_u64); + _34 = opaque::(move _35) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb19, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb19, unwind unreachable]; + } + + bb19: { +- _39 = Rem(move _40, const 1_u64); +- StorageDead(_40); ++ _39 = Rem(_1, const 1_u64); + _38 = opaque::(move _39) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind unreachable]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind unreachable]; + } + + bb21: { +- _43 = Rem(const 0_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 0_u64, _1); + _42 = opaque::(move _43) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind unreachable]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind unreachable]; + } + + bb23: { +- _47 = Rem(const 1_u64, move _48); +- StorageDead(_48); ++ _47 = Rem(const 1_u64, _1); + _46 = opaque::(move _47) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); +- StorageDead(_52); ++ _51 = BitAnd(_1, const 0_u64); + _50 = opaque::(move _51) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _1; +- _54 = BitOr(move _55, const 0_u64); +- StorageDead(_55); ++ _54 = BitOr(_1, const 0_u64); + _53 = opaque::(move _54) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = BitXor(move _58, const 0_u64); +- StorageDead(_58); ++ _57 = BitXor(_1, const 0_u64); + _56 = opaque::(move _57) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _1; + _62 = const 0_i32 as u32 (IntToInt); +- _63 = Lt(move _62, const 64_u32); +- assert(move _63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind unreachable]; ++ _63 = Lt(_62, const 64_u32); ++ assert(_63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind unreachable]; + } + + bb28: { +- _60 = Shr(move _61, const 0_i32); +- StorageDead(_61); ++ _60 = Shr(_1, const 0_i32); + _59 = opaque::(move _60) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_64); + StorageLive(_65); +- StorageLive(_66); +- _66 = _1; +- _67 = const 0_i32 as u32 (IntToInt); +- _68 = Lt(move _67, const 64_u32); +- assert(move _68, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind unreachable]; ++ assert(_63, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind unreachable]; + } + + bb30: { +- _65 = Shl(move _66, const 0_i32); +- StorageDead(_66); ++ _65 = Shl(_1, const 0_i32); + _64 = opaque::(move _65) -> [return: bb31, unwind unreachable]; + } + + bb31: { + StorageDead(_65); + StorageDead(_64); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..7813c29b962d2 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -0,0 +1,389 @@ +- // MIR for `arithmetic_checked` before GVN ++ // MIR for `arithmetic_checked` after GVN + + fn arithmetic_checked(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let mut _5: (u64, bool); + let _6: (); + let mut _7: u64; + let mut _8: u64; + let mut _9: (u64, bool); + let _10: (); + let mut _11: u64; + let mut _12: u64; + let mut _13: (u64, bool); + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: (u64, bool); + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let mut _49: bool; + let _50: (); + let mut _51: u64; + let mut _52: u64; + let _53: (); + let mut _54: u64; + let mut _55: u64; + let _56: (); + let mut _57: u64; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u32; + let mut _63: bool; + let _64: (); + let mut _65: u64; + let mut _66: u64; + let mut _67: u32; + let mut _68: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _5 = CheckedAdd(_4, const 0_u64); +- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue]; ++ _5 = CheckedAdd(_1, const 0_u64); ++ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; + } + + bb1: { + _3 = move (_5.0: u64); +- StorageDead(_4); + _2 = opaque::(move _3) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_6); + StorageLive(_7); +- StorageLive(_8); +- _8 = _1; +- _9 = CheckedSub(_8, const 0_u64); +- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue]; ++ _9 = CheckedSub(_1, const 0_u64); ++ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; + } + + bb3: { + _7 = move (_9.0: u64); +- StorageDead(_8); + _6 = opaque::(move _7) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _13 = CheckedMul(_12, const 0_u64); +- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind continue]; ++ _13 = CheckedMul(_1, const 0_u64); ++ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind continue]; + } + + bb5: { + _11 = move (_13.0: u64); +- StorageDead(_12); + _10 = opaque::(move _11) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _17 = CheckedMul(_16, const 1_u64); +- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind continue]; ++ _17 = CheckedMul(_1, const 1_u64); ++ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind continue]; + } + + bb7: { + _15 = move (_17.0: u64); +- StorageDead(_16); + _14 = opaque::(move _15) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb9, unwind continue]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb9, unwind continue]; + } + + bb9: { +- _19 = Div(move _20, const 0_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 0_u64); + _18 = opaque::(move _19) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; + _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb11, unwind continue]; ++ assert(!_25, "attempt to divide `{}` by zero", _1) -> [success: bb11, unwind continue]; + } + + bb11: { +- _23 = Div(move _24, const 1_u64); +- StorageDead(_24); ++ _23 = Div(_1, const 1_u64); + _22 = opaque::(move _23) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind continue]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind continue]; + } + + bb13: { +- _27 = Div(const 0_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 0_u64, _1); + _26 = opaque::(move _27) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind continue]; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind continue]; + } + + bb15: { +- _31 = Div(const 1_u64, move _32); +- StorageDead(_32); ++ _31 = Div(const 1_u64, _1); + _30 = opaque::(move _31) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb17, unwind continue]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb17, unwind continue]; + } + + bb17: { +- _35 = Rem(move _36, const 0_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 0_u64); + _34 = opaque::(move _35) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb19, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb19, unwind continue]; + } + + bb19: { +- _39 = Rem(move _40, const 1_u64); +- StorageDead(_40); ++ _39 = Rem(_1, const 1_u64); + _38 = opaque::(move _39) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind continue]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind continue]; + } + + bb21: { +- _43 = Rem(const 0_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 0_u64, _1); + _42 = opaque::(move _43) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind continue]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind continue]; + } + + bb23: { +- _47 = Rem(const 1_u64, move _48); +- StorageDead(_48); ++ _47 = Rem(const 1_u64, _1); + _46 = opaque::(move _47) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); +- StorageDead(_52); ++ _51 = BitAnd(_1, const 0_u64); + _50 = opaque::(move _51) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _1; +- _54 = BitOr(move _55, const 0_u64); +- StorageDead(_55); ++ _54 = BitOr(_1, const 0_u64); + _53 = opaque::(move _54) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = BitXor(move _58, const 0_u64); +- StorageDead(_58); ++ _57 = BitXor(_1, const 0_u64); + _56 = opaque::(move _57) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _1; + _62 = const 0_i32 as u32 (IntToInt); +- _63 = Lt(move _62, const 64_u32); +- assert(move _63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind continue]; ++ _63 = Lt(_62, const 64_u32); ++ assert(_63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind continue]; + } + + bb28: { +- _60 = Shr(move _61, const 0_i32); +- StorageDead(_61); ++ _60 = Shr(_1, const 0_i32); + _59 = opaque::(move _60) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_64); + StorageLive(_65); +- StorageLive(_66); +- _66 = _1; +- _67 = const 0_i32 as u32 (IntToInt); +- _68 = Lt(move _67, const 64_u32); +- assert(move _68, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind continue]; ++ assert(_63, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind continue]; + } + + bb30: { +- _65 = Shl(move _66, const 0_i32); +- StorageDead(_66); ++ _65 = Shl(_1, const 0_i32); + _64 = opaque::(move _65) -> [return: bb31, unwind continue]; + } + + bb31: { + StorageDead(_65); + StorageDead(_64); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff new file mode 100644 index 0000000000000..7d5ac8353fe43 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff @@ -0,0 +1,165 @@ +- // MIR for `arithmetic_float` before GVN ++ // MIR for `arithmetic_float` after GVN + + fn arithmetic_float(_1: f64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: f64; + let mut _4: f64; + let _5: (); + let mut _6: f64; + let mut _7: f64; + let _8: (); + let mut _9: f64; + let mut _10: f64; + let _11: (); + let mut _12: f64; + let mut _13: f64; + let _14: (); + let mut _15: f64; + let mut _16: f64; + let _17: (); + let mut _18: f64; + let mut _19: f64; + let _20: (); + let mut _21: f64; + let mut _22: f64; + let _23: (); + let mut _24: bool; + let mut _25: f64; + let mut _26: f64; + let _27: (); + let mut _28: bool; + let mut _29: f64; + let mut _30: f64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0f64); +- StorageDead(_4); ++ _3 = Add(_1, const 0f64); + _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0f64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0f64); + _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0f64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0f64); + _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Div(move _13, const 0f64); +- StorageDead(_13); ++ _12 = Div(_1, const 0f64); + _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _15 = Div(const 0f64, move _16); +- StorageDead(_16); ++ _15 = Div(const 0f64, _1); + _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); +- StorageLive(_19); +- _19 = _1; +- _18 = Rem(move _19, const 0f64); +- StorageDead(_19); ++ _18 = Rem(_1, const 0f64); + _17 = opaque::(move _18) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); + StorageLive(_21); +- StorageLive(_22); +- _22 = _1; +- _21 = Rem(const 0f64, move _22); +- StorageDead(_22); ++ _21 = Rem(const 0f64, _1); + _20 = opaque::(move _21) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_21); + StorageDead(_20); + StorageLive(_23); + StorageLive(_24); +- StorageLive(_25); +- _25 = _1; +- StorageLive(_26); +- _26 = _1; +- _24 = Eq(move _25, move _26); +- StorageDead(_26); +- StorageDead(_25); ++ _24 = Eq(_1, _1); + _23 = opaque::(move _24) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- StorageLive(_30); +- _30 = _1; +- _28 = Ne(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); ++ _28 = Ne(_1, _1); + _27 = opaque::(move _28) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..36c26dc66051b --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff @@ -0,0 +1,165 @@ +- // MIR for `arithmetic_float` before GVN ++ // MIR for `arithmetic_float` after GVN + + fn arithmetic_float(_1: f64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: f64; + let mut _4: f64; + let _5: (); + let mut _6: f64; + let mut _7: f64; + let _8: (); + let mut _9: f64; + let mut _10: f64; + let _11: (); + let mut _12: f64; + let mut _13: f64; + let _14: (); + let mut _15: f64; + let mut _16: f64; + let _17: (); + let mut _18: f64; + let mut _19: f64; + let _20: (); + let mut _21: f64; + let mut _22: f64; + let _23: (); + let mut _24: bool; + let mut _25: f64; + let mut _26: f64; + let _27: (); + let mut _28: bool; + let mut _29: f64; + let mut _30: f64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0f64); +- StorageDead(_4); ++ _3 = Add(_1, const 0f64); + _2 = opaque::(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0f64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0f64); + _5 = opaque::(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0f64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0f64); + _8 = opaque::(move _9) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Div(move _13, const 0f64); +- StorageDead(_13); ++ _12 = Div(_1, const 0f64); + _11 = opaque::(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _15 = Div(const 0f64, move _16); +- StorageDead(_16); ++ _15 = Div(const 0f64, _1); + _14 = opaque::(move _15) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); +- StorageLive(_19); +- _19 = _1; +- _18 = Rem(move _19, const 0f64); +- StorageDead(_19); ++ _18 = Rem(_1, const 0f64); + _17 = opaque::(move _18) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); + StorageLive(_21); +- StorageLive(_22); +- _22 = _1; +- _21 = Rem(const 0f64, move _22); +- StorageDead(_22); ++ _21 = Rem(const 0f64, _1); + _20 = opaque::(move _21) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_21); + StorageDead(_20); + StorageLive(_23); + StorageLive(_24); +- StorageLive(_25); +- _25 = _1; +- StorageLive(_26); +- _26 = _1; +- _24 = Eq(move _25, move _26); +- StorageDead(_26); +- StorageDead(_25); ++ _24 = Eq(_1, _1); + _23 = opaque::(move _24) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- StorageLive(_30); +- _30 = _1; +- _28 = Ne(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); ++ _28 = Ne(_1, _1); + _27 = opaque::(move _28) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.cast.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff new file mode 100644 index 0000000000000..513fe60b65d93 --- /dev/null +++ b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff @@ -0,0 +1,501 @@ +- // MIR for `cast` before GVN ++ // MIR for `cast` after GVN + + fn cast() -> () { + let mut _0: (); + let _1: i64; + let _4: (); + let mut _5: u8; + let mut _6: i64; + let _7: (); + let mut _8: u16; + let mut _9: i64; + let _10: (); + let mut _11: u32; + let mut _12: i64; + let _13: (); + let mut _14: u64; + let mut _15: i64; + let _16: (); + let mut _17: i8; + let mut _18: i64; + let _19: (); + let mut _20: i16; + let mut _21: i64; + let _22: (); + let mut _23: i32; + let mut _24: i64; + let _25: (); + let mut _26: i64; + let _27: (); + let mut _28: f32; + let mut _29: i64; + let _30: (); + let mut _31: f64; + let mut _32: i64; + let _33: (); + let mut _34: u8; + let mut _35: u64; + let _36: (); + let mut _37: u16; + let mut _38: u64; + let _39: (); + let mut _40: u32; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let _44: (); + let mut _45: i8; + let mut _46: u64; + let _47: (); + let mut _48: i16; + let mut _49: u64; + let _50: (); + let mut _51: i32; + let mut _52: u64; + let _53: (); + let mut _54: i64; + let mut _55: u64; + let _56: (); + let mut _57: f32; + let mut _58: u64; + let _59: (); + let mut _60: f64; + let mut _61: u64; + let _62: (); + let mut _63: u8; + let mut _64: f64; + let _65: (); + let mut _66: u16; + let mut _67: f64; + let _68: (); + let mut _69: u32; + let mut _70: f64; + let _71: (); + let mut _72: u64; + let mut _73: f64; + let _74: (); + let mut _75: i8; + let mut _76: f64; + let _77: (); + let mut _78: i16; + let mut _79: f64; + let _80: (); + let mut _81: i32; + let mut _82: f64; + let _83: (); + let mut _84: i64; + let mut _85: f64; + let _86: (); + let mut _87: f32; + let mut _88: f64; + let _89: (); + let mut _90: f64; + scope 1 { + debug i => _1; + let _2: u64; + scope 2 { + debug u => _2; + let _3: f64; + scope 3 { + debug f => _3; + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const 1_i64; +- StorageLive(_2); + _2 = const 1_u64; +- StorageLive(_3); + _3 = const 1f64; + StorageLive(_4); + StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- _5 = move _6 as u8 (IntToInt); +- StorageDead(_6); ++ _5 = const 1_i64 as u8 (IntToInt); + _4 = opaque::(move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_7); + StorageLive(_8); +- StorageLive(_9); +- _9 = _1; +- _8 = move _9 as u16 (IntToInt); +- StorageDead(_9); ++ _8 = const 1_i64 as u16 (IntToInt); + _7 = opaque::(move _8) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _11 = move _12 as u32 (IntToInt); +- StorageDead(_12); ++ _11 = const 1_i64 as u32 (IntToInt); + _10 = opaque::(move _11) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_13); + StorageLive(_14); +- StorageLive(_15); +- _15 = _1; +- _14 = move _15 as u64 (IntToInt); +- StorageDead(_15); ++ _14 = const 1_i64 as u64 (IntToInt); + _13 = opaque::(move _14) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_14); + StorageDead(_13); + StorageLive(_16); + StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- _17 = move _18 as i8 (IntToInt); +- StorageDead(_18); ++ _17 = const 1_i64 as i8 (IntToInt); + _16 = opaque::(move _17) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_19); + StorageLive(_20); +- StorageLive(_21); +- _21 = _1; +- _20 = move _21 as i16 (IntToInt); +- StorageDead(_21); ++ _20 = const 1_i64 as i16 (IntToInt); + _19 = opaque::(move _20) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_20); + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _23 = move _24 as i32 (IntToInt); +- StorageDead(_24); ++ _23 = const 1_i64 as i32 (IntToInt); + _22 = opaque::(move _23) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); +- StorageLive(_26); +- _26 = _1; +- _25 = opaque::(move _26) -> [return: bb8, unwind unreachable]; ++ _25 = opaque::(const 1_i64) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- _28 = move _29 as f32 (IntToFloat); +- StorageDead(_29); ++ _28 = const 1_i64 as f32 (IntToFloat); + _27 = opaque::(move _28) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _31 = move _32 as f64 (IntToFloat); +- StorageDead(_32); ++ _31 = const 1_i64 as f64 (IntToFloat); + _30 = opaque::(move _31) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); +- StorageLive(_35); +- _35 = _2; +- _34 = move _35 as u8 (IntToInt); +- StorageDead(_35); ++ _34 = const 1_u64 as u8 (IntToInt); + _33 = opaque::(move _34) -> [return: bb11, unwind unreachable]; + } + + bb11: { + StorageDead(_34); + StorageDead(_33); + StorageLive(_36); + StorageLive(_37); +- StorageLive(_38); +- _38 = _2; +- _37 = move _38 as u16 (IntToInt); +- StorageDead(_38); ++ _37 = const 1_u64 as u16 (IntToInt); + _36 = opaque::(move _37) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_37); + StorageDead(_36); + StorageLive(_39); + StorageLive(_40); +- StorageLive(_41); +- _41 = _2; +- _40 = move _41 as u32 (IntToInt); +- StorageDead(_41); ++ _40 = const 1_u64 as u32 (IntToInt); + _39 = opaque::(move _40) -> [return: bb13, unwind unreachable]; + } + + bb13: { + StorageDead(_40); + StorageDead(_39); + StorageLive(_42); +- StorageLive(_43); +- _43 = _2; +- _42 = opaque::(move _43) -> [return: bb14, unwind unreachable]; ++ _42 = opaque::(const 1_u64) -> [return: bb14, unwind unreachable]; + } + + bb14: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_44); + StorageLive(_45); +- StorageLive(_46); +- _46 = _2; +- _45 = move _46 as i8 (IntToInt); +- StorageDead(_46); ++ _45 = const 1_u64 as i8 (IntToInt); + _44 = opaque::(move _45) -> [return: bb15, unwind unreachable]; + } + + bb15: { + StorageDead(_45); + StorageDead(_44); + StorageLive(_47); + StorageLive(_48); +- StorageLive(_49); +- _49 = _2; +- _48 = move _49 as i16 (IntToInt); +- StorageDead(_49); ++ _48 = const 1_u64 as i16 (IntToInt); + _47 = opaque::(move _48) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_48); + StorageDead(_47); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _2; +- _51 = move _52 as i32 (IntToInt); +- StorageDead(_52); ++ _51 = const 1_u64 as i32 (IntToInt); + _50 = opaque::(move _51) -> [return: bb17, unwind unreachable]; + } + + bb17: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _2; +- _54 = move _55 as i64 (IntToInt); +- StorageDead(_55); ++ _54 = const 1_u64 as i64 (IntToInt); + _53 = opaque::(move _54) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _2; +- _57 = move _58 as f32 (IntToFloat); +- StorageDead(_58); ++ _57 = const 1_u64 as f32 (IntToFloat); + _56 = opaque::(move _57) -> [return: bb19, unwind unreachable]; + } + + bb19: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _2; +- _60 = move _61 as f64 (IntToFloat); +- StorageDead(_61); ++ _60 = const 1_u64 as f64 (IntToFloat); + _59 = opaque::(move _60) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_62); + StorageLive(_63); +- StorageLive(_64); +- _64 = _3; +- _63 = move _64 as u8 (FloatToInt); +- StorageDead(_64); ++ _63 = const 1f64 as u8 (FloatToInt); + _62 = opaque::(move _63) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- _67 = _3; +- _66 = move _67 as u16 (FloatToInt); +- StorageDead(_67); ++ _66 = const 1f64 as u16 (FloatToInt); + _65 = opaque::(move _66) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_68); + StorageLive(_69); +- StorageLive(_70); +- _70 = _3; +- _69 = move _70 as u32 (FloatToInt); +- StorageDead(_70); ++ _69 = const 1f64 as u32 (FloatToInt); + _68 = opaque::(move _69) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_69); + StorageDead(_68); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- _73 = _3; +- _72 = move _73 as u64 (FloatToInt); +- StorageDead(_73); ++ _72 = const 1f64 as u64 (FloatToInt); + _71 = opaque::(move _72) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_74); + StorageLive(_75); +- StorageLive(_76); +- _76 = _3; +- _75 = move _76 as i8 (FloatToInt); +- StorageDead(_76); ++ _75 = const 1f64 as i8 (FloatToInt); + _74 = opaque::(move _75) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_75); + StorageDead(_74); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- _79 = _3; +- _78 = move _79 as i16 (FloatToInt); +- StorageDead(_79); ++ _78 = const 1f64 as i16 (FloatToInt); + _77 = opaque::(move _78) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_80); + StorageLive(_81); +- StorageLive(_82); +- _82 = _3; +- _81 = move _82 as i32 (FloatToInt); +- StorageDead(_82); ++ _81 = const 1f64 as i32 (FloatToInt); + _80 = opaque::(move _81) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_81); + StorageDead(_80); + StorageLive(_83); + StorageLive(_84); +- StorageLive(_85); +- _85 = _3; +- _84 = move _85 as i64 (FloatToInt); +- StorageDead(_85); ++ _84 = const 1f64 as i64 (FloatToInt); + _83 = opaque::(move _84) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_84); + StorageDead(_83); + StorageLive(_86); + StorageLive(_87); +- StorageLive(_88); +- _88 = _3; +- _87 = move _88 as f32 (FloatToFloat); +- StorageDead(_88); ++ _87 = const 1f64 as f32 (FloatToFloat); + _86 = opaque::(move _87) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_87); + StorageDead(_86); + StorageLive(_89); +- StorageLive(_90); +- _90 = _3; +- _89 = opaque::(move _90) -> [return: bb30, unwind unreachable]; ++ _89 = opaque::(const 1f64) -> [return: bb30, unwind unreachable]; + } + + bb30: { +- StorageDead(_90); + StorageDead(_89); + _0 = const (); +- StorageDead(_3); +- StorageDead(_2); +- StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..33192ed8de033 --- /dev/null +++ b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff @@ -0,0 +1,501 @@ +- // MIR for `cast` before GVN ++ // MIR for `cast` after GVN + + fn cast() -> () { + let mut _0: (); + let _1: i64; + let _4: (); + let mut _5: u8; + let mut _6: i64; + let _7: (); + let mut _8: u16; + let mut _9: i64; + let _10: (); + let mut _11: u32; + let mut _12: i64; + let _13: (); + let mut _14: u64; + let mut _15: i64; + let _16: (); + let mut _17: i8; + let mut _18: i64; + let _19: (); + let mut _20: i16; + let mut _21: i64; + let _22: (); + let mut _23: i32; + let mut _24: i64; + let _25: (); + let mut _26: i64; + let _27: (); + let mut _28: f32; + let mut _29: i64; + let _30: (); + let mut _31: f64; + let mut _32: i64; + let _33: (); + let mut _34: u8; + let mut _35: u64; + let _36: (); + let mut _37: u16; + let mut _38: u64; + let _39: (); + let mut _40: u32; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let _44: (); + let mut _45: i8; + let mut _46: u64; + let _47: (); + let mut _48: i16; + let mut _49: u64; + let _50: (); + let mut _51: i32; + let mut _52: u64; + let _53: (); + let mut _54: i64; + let mut _55: u64; + let _56: (); + let mut _57: f32; + let mut _58: u64; + let _59: (); + let mut _60: f64; + let mut _61: u64; + let _62: (); + let mut _63: u8; + let mut _64: f64; + let _65: (); + let mut _66: u16; + let mut _67: f64; + let _68: (); + let mut _69: u32; + let mut _70: f64; + let _71: (); + let mut _72: u64; + let mut _73: f64; + let _74: (); + let mut _75: i8; + let mut _76: f64; + let _77: (); + let mut _78: i16; + let mut _79: f64; + let _80: (); + let mut _81: i32; + let mut _82: f64; + let _83: (); + let mut _84: i64; + let mut _85: f64; + let _86: (); + let mut _87: f32; + let mut _88: f64; + let _89: (); + let mut _90: f64; + scope 1 { + debug i => _1; + let _2: u64; + scope 2 { + debug u => _2; + let _3: f64; + scope 3 { + debug f => _3; + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const 1_i64; +- StorageLive(_2); + _2 = const 1_u64; +- StorageLive(_3); + _3 = const 1f64; + StorageLive(_4); + StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- _5 = move _6 as u8 (IntToInt); +- StorageDead(_6); ++ _5 = const 1_i64 as u8 (IntToInt); + _4 = opaque::(move _5) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_7); + StorageLive(_8); +- StorageLive(_9); +- _9 = _1; +- _8 = move _9 as u16 (IntToInt); +- StorageDead(_9); ++ _8 = const 1_i64 as u16 (IntToInt); + _7 = opaque::(move _8) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _11 = move _12 as u32 (IntToInt); +- StorageDead(_12); ++ _11 = const 1_i64 as u32 (IntToInt); + _10 = opaque::(move _11) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_13); + StorageLive(_14); +- StorageLive(_15); +- _15 = _1; +- _14 = move _15 as u64 (IntToInt); +- StorageDead(_15); ++ _14 = const 1_i64 as u64 (IntToInt); + _13 = opaque::(move _14) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_14); + StorageDead(_13); + StorageLive(_16); + StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- _17 = move _18 as i8 (IntToInt); +- StorageDead(_18); ++ _17 = const 1_i64 as i8 (IntToInt); + _16 = opaque::(move _17) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_19); + StorageLive(_20); +- StorageLive(_21); +- _21 = _1; +- _20 = move _21 as i16 (IntToInt); +- StorageDead(_21); ++ _20 = const 1_i64 as i16 (IntToInt); + _19 = opaque::(move _20) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_20); + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _23 = move _24 as i32 (IntToInt); +- StorageDead(_24); ++ _23 = const 1_i64 as i32 (IntToInt); + _22 = opaque::(move _23) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); +- StorageLive(_26); +- _26 = _1; +- _25 = opaque::(move _26) -> [return: bb8, unwind continue]; ++ _25 = opaque::(const 1_i64) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- _28 = move _29 as f32 (IntToFloat); +- StorageDead(_29); ++ _28 = const 1_i64 as f32 (IntToFloat); + _27 = opaque::(move _28) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _31 = move _32 as f64 (IntToFloat); +- StorageDead(_32); ++ _31 = const 1_i64 as f64 (IntToFloat); + _30 = opaque::(move _31) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); +- StorageLive(_35); +- _35 = _2; +- _34 = move _35 as u8 (IntToInt); +- StorageDead(_35); ++ _34 = const 1_u64 as u8 (IntToInt); + _33 = opaque::(move _34) -> [return: bb11, unwind continue]; + } + + bb11: { + StorageDead(_34); + StorageDead(_33); + StorageLive(_36); + StorageLive(_37); +- StorageLive(_38); +- _38 = _2; +- _37 = move _38 as u16 (IntToInt); +- StorageDead(_38); ++ _37 = const 1_u64 as u16 (IntToInt); + _36 = opaque::(move _37) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_37); + StorageDead(_36); + StorageLive(_39); + StorageLive(_40); +- StorageLive(_41); +- _41 = _2; +- _40 = move _41 as u32 (IntToInt); +- StorageDead(_41); ++ _40 = const 1_u64 as u32 (IntToInt); + _39 = opaque::(move _40) -> [return: bb13, unwind continue]; + } + + bb13: { + StorageDead(_40); + StorageDead(_39); + StorageLive(_42); +- StorageLive(_43); +- _43 = _2; +- _42 = opaque::(move _43) -> [return: bb14, unwind continue]; ++ _42 = opaque::(const 1_u64) -> [return: bb14, unwind continue]; + } + + bb14: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_44); + StorageLive(_45); +- StorageLive(_46); +- _46 = _2; +- _45 = move _46 as i8 (IntToInt); +- StorageDead(_46); ++ _45 = const 1_u64 as i8 (IntToInt); + _44 = opaque::(move _45) -> [return: bb15, unwind continue]; + } + + bb15: { + StorageDead(_45); + StorageDead(_44); + StorageLive(_47); + StorageLive(_48); +- StorageLive(_49); +- _49 = _2; +- _48 = move _49 as i16 (IntToInt); +- StorageDead(_49); ++ _48 = const 1_u64 as i16 (IntToInt); + _47 = opaque::(move _48) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_48); + StorageDead(_47); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _2; +- _51 = move _52 as i32 (IntToInt); +- StorageDead(_52); ++ _51 = const 1_u64 as i32 (IntToInt); + _50 = opaque::(move _51) -> [return: bb17, unwind continue]; + } + + bb17: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _2; +- _54 = move _55 as i64 (IntToInt); +- StorageDead(_55); ++ _54 = const 1_u64 as i64 (IntToInt); + _53 = opaque::(move _54) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _2; +- _57 = move _58 as f32 (IntToFloat); +- StorageDead(_58); ++ _57 = const 1_u64 as f32 (IntToFloat); + _56 = opaque::(move _57) -> [return: bb19, unwind continue]; + } + + bb19: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _2; +- _60 = move _61 as f64 (IntToFloat); +- StorageDead(_61); ++ _60 = const 1_u64 as f64 (IntToFloat); + _59 = opaque::(move _60) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_62); + StorageLive(_63); +- StorageLive(_64); +- _64 = _3; +- _63 = move _64 as u8 (FloatToInt); +- StorageDead(_64); ++ _63 = const 1f64 as u8 (FloatToInt); + _62 = opaque::(move _63) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- _67 = _3; +- _66 = move _67 as u16 (FloatToInt); +- StorageDead(_67); ++ _66 = const 1f64 as u16 (FloatToInt); + _65 = opaque::(move _66) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_68); + StorageLive(_69); +- StorageLive(_70); +- _70 = _3; +- _69 = move _70 as u32 (FloatToInt); +- StorageDead(_70); ++ _69 = const 1f64 as u32 (FloatToInt); + _68 = opaque::(move _69) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_69); + StorageDead(_68); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- _73 = _3; +- _72 = move _73 as u64 (FloatToInt); +- StorageDead(_73); ++ _72 = const 1f64 as u64 (FloatToInt); + _71 = opaque::(move _72) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_74); + StorageLive(_75); +- StorageLive(_76); +- _76 = _3; +- _75 = move _76 as i8 (FloatToInt); +- StorageDead(_76); ++ _75 = const 1f64 as i8 (FloatToInt); + _74 = opaque::(move _75) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_75); + StorageDead(_74); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- _79 = _3; +- _78 = move _79 as i16 (FloatToInt); +- StorageDead(_79); ++ _78 = const 1f64 as i16 (FloatToInt); + _77 = opaque::(move _78) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_80); + StorageLive(_81); +- StorageLive(_82); +- _82 = _3; +- _81 = move _82 as i32 (FloatToInt); +- StorageDead(_82); ++ _81 = const 1f64 as i32 (FloatToInt); + _80 = opaque::(move _81) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_81); + StorageDead(_80); + StorageLive(_83); + StorageLive(_84); +- StorageLive(_85); +- _85 = _3; +- _84 = move _85 as i64 (FloatToInt); +- StorageDead(_85); ++ _84 = const 1f64 as i64 (FloatToInt); + _83 = opaque::(move _84) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_84); + StorageDead(_83); + StorageLive(_86); + StorageLive(_87); +- StorageLive(_88); +- _88 = _3; +- _87 = move _88 as f32 (FloatToFloat); +- StorageDead(_88); ++ _87 = const 1f64 as f32 (FloatToFloat); + _86 = opaque::(move _87) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_87); + StorageDead(_86); + StorageLive(_89); +- StorageLive(_90); +- _90 = _3; +- _89 = opaque::(move _90) -> [return: bb30, unwind continue]; ++ _89 = opaque::(const 1f64) -> [return: bb30, unwind continue]; + } + + bb30: { +- StorageDead(_90); + StorageDead(_89); + _0 = const (); +- StorageDead(_3); +- StorageDead(_2); +- StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff new file mode 100644 index 0000000000000..ee320cf678701 --- /dev/null +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -0,0 +1,191 @@ +- // MIR for `dereferences` before GVN ++ // MIR for `dereferences` after GVN + + fn dereferences(_1: &mut u32, _2: &impl Copy, _3: &S) -> () { + debug t => _1; + debug u => _2; + debug s => _3; + let mut _0: (); + let _4: (); + let mut _5: u32; + let _6: (); + let mut _7: u32; + let _8: *const u32; + let _9: (); + let mut _10: u32; + let _11: (); + let mut _12: u32; + let _14: (); + let mut _15: u32; + let _16: (); + let mut _17: u32; + let _19: (); + let mut _20: u32; + let _21: (); + let mut _22: u32; + let _23: (); + let mut _24: &u32; + let _25: (); + let mut _26: impl Copy; + let _27: (); + let mut _28: impl Copy; + let _29: (); + let mut _30: u32; + let _31: (); + let mut _32: u32; + scope 1 { + debug z => _8; + let _13: *mut u32; + scope 2 { + } + scope 3 { + } + scope 4 { + debug z => _13; + let _18: &u32; + scope 5 { + } + scope 6 { + } + scope 7 { + debug z => _18; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = (*_1); + _4 = opaque::(move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = (*_1); + _6 = opaque::(move _7) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + _8 = &raw const (*_1); + StorageLive(_9); + StorageLive(_10); + _10 = (*_8); + _9 = opaque::(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = (*_8); + _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_13); + _13 = &raw mut (*_1); + StorageLive(_14); + StorageLive(_15); + _15 = (*_13); + _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = (*_13); + _16 = opaque::(move _17) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + _18 = &(*_1); + StorageLive(_19); +- StorageLive(_20); + _20 = (*_18); +- _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; ++ _19 = opaque::(_20) -> [return: bb7, unwind unreachable]; + } + + bb7: { +- StorageDead(_20); + StorageDead(_19); + StorageLive(_21); +- StorageLive(_22); +- _22 = (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; ++ _21 = opaque::(_20) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_23); + StorageLive(_24); + _24 = &(*_18); + _23 = opaque::<&u32>(move _24) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_25); + StorageLive(_26); + _26 = (*_2); + _25 = opaque::(move _26) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); + _28 = (*_2); + _27 = opaque::(move _28) -> [return: bb11, unwind unreachable]; + } + + bb11: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_29); +- StorageLive(_30); + _30 = ((*_3).0: u32); +- _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; ++ _29 = opaque::(_30) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_30); + StorageDead(_29); + StorageLive(_31); +- StorageLive(_32); +- _32 = ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; ++ _31 = opaque::(_30) -> [return: bb13, unwind unreachable]; + } + + bb13: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..f627b4d59887a --- /dev/null +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -0,0 +1,191 @@ +- // MIR for `dereferences` before GVN ++ // MIR for `dereferences` after GVN + + fn dereferences(_1: &mut u32, _2: &impl Copy, _3: &S) -> () { + debug t => _1; + debug u => _2; + debug s => _3; + let mut _0: (); + let _4: (); + let mut _5: u32; + let _6: (); + let mut _7: u32; + let _8: *const u32; + let _9: (); + let mut _10: u32; + let _11: (); + let mut _12: u32; + let _14: (); + let mut _15: u32; + let _16: (); + let mut _17: u32; + let _19: (); + let mut _20: u32; + let _21: (); + let mut _22: u32; + let _23: (); + let mut _24: &u32; + let _25: (); + let mut _26: impl Copy; + let _27: (); + let mut _28: impl Copy; + let _29: (); + let mut _30: u32; + let _31: (); + let mut _32: u32; + scope 1 { + debug z => _8; + let _13: *mut u32; + scope 2 { + } + scope 3 { + } + scope 4 { + debug z => _13; + let _18: &u32; + scope 5 { + } + scope 6 { + } + scope 7 { + debug z => _18; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = (*_1); + _4 = opaque::(move _5) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = (*_1); + _6 = opaque::(move _7) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + _8 = &raw const (*_1); + StorageLive(_9); + StorageLive(_10); + _10 = (*_8); + _9 = opaque::(move _10) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = (*_8); + _11 = opaque::(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_13); + _13 = &raw mut (*_1); + StorageLive(_14); + StorageLive(_15); + _15 = (*_13); + _14 = opaque::(move _15) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = (*_13); + _16 = opaque::(move _17) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + _18 = &(*_1); + StorageLive(_19); +- StorageLive(_20); + _20 = (*_18); +- _19 = opaque::(move _20) -> [return: bb7, unwind continue]; ++ _19 = opaque::(_20) -> [return: bb7, unwind continue]; + } + + bb7: { +- StorageDead(_20); + StorageDead(_19); + StorageLive(_21); +- StorageLive(_22); +- _22 = (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind continue]; ++ _21 = opaque::(_20) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_23); + StorageLive(_24); + _24 = &(*_18); + _23 = opaque::<&u32>(move _24) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_25); + StorageLive(_26); + _26 = (*_2); + _25 = opaque::(move _26) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); + _28 = (*_2); + _27 = opaque::(move _28) -> [return: bb11, unwind continue]; + } + + bb11: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_29); +- StorageLive(_30); + _30 = ((*_3).0: u32); +- _29 = opaque::(move _30) -> [return: bb12, unwind continue]; ++ _29 = opaque::(_30) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_30); + StorageDead(_29); + StorageLive(_31); +- StorageLive(_32); +- _32 = ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind continue]; ++ _31 = opaque::(_30) -> [return: bb13, unwind continue]; + } + + bb13: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); + return; + } + } + diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff new file mode 100644 index 0000000000000..0a66900283b61 --- /dev/null +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff @@ -0,0 +1,198 @@ +- // MIR for `multiple_branches` before GVN ++ // MIR for `multiple_branches` after GVN + + fn multiple_branches(_1: bool, _2: u8, _3: u8) -> () { + debug t => _1; + debug x => _2; + debug y => _3; + let mut _0: (); + let _4: (); + let mut _5: bool; + let _6: (); + let mut _7: u8; + let mut _8: u8; + let mut _9: u8; + let _10: (); + let mut _11: u8; + let mut _12: u8; + let mut _13: u8; + let _14: (); + let mut _15: u8; + let mut _16: u8; + let mut _17: u8; + let _18: (); + let mut _19: u8; + let mut _20: u8; + let mut _21: u8; + let _22: (); + let mut _23: u8; + let mut _24: u8; + let mut _25: u8; + let mut _26: bool; + let _27: (); + let mut _28: u8; + let mut _29: u8; + let mut _30: u8; + let _31: (); + let mut _32: u8; + let mut _33: u8; + let mut _34: u8; + + bb0: { +- StorageLive(_4); +- StorageLive(_5); +- _5 = _1; +- switchInt(move _5) -> [0: bb4, otherwise: bb1]; ++ switchInt(_1) -> [0: bb4, otherwise: bb1]; + } + + bb1: { + StorageLive(_6); +- StorageLive(_7); +- StorageLive(_8); +- _8 = _2; +- StorageLive(_9); +- _9 = _3; +- _7 = Add(move _8, move _9); +- StorageDead(_9); +- StorageDead(_8); +- _6 = opaque::(move _7) -> [return: bb2, unwind unreachable]; ++ _7 = Add(_2, _3); ++ _6 = opaque::(_7) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_7); + StorageDead(_6); + StorageLive(_10); +- StorageLive(_11); +- StorageLive(_12); +- _12 = _2; +- StorageLive(_13); +- _13 = _3; +- _11 = Add(move _12, move _13); +- StorageDead(_13); +- StorageDead(_12); +- _10 = opaque::(move _11) -> [return: bb3, unwind unreachable]; ++ _10 = opaque::(_7) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_11); + StorageDead(_10); +- _4 = const (); + goto -> bb7; + } + + bb4: { + StorageLive(_14); +- StorageLive(_15); +- StorageLive(_16); +- _16 = _2; +- StorageLive(_17); +- _17 = _3; +- _15 = Add(move _16, move _17); +- StorageDead(_17); +- StorageDead(_16); +- _14 = opaque::(move _15) -> [return: bb5, unwind unreachable]; ++ _15 = Add(_2, _3); ++ _14 = opaque::(_15) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_15); + StorageDead(_14); + StorageLive(_18); +- StorageLive(_19); +- StorageLive(_20); +- _20 = _2; +- StorageLive(_21); +- _21 = _3; +- _19 = Add(move _20, move _21); +- StorageDead(_21); +- StorageDead(_20); +- _18 = opaque::(move _19) -> [return: bb6, unwind unreachable]; ++ _18 = opaque::(_15) -> [return: bb6, unwind unreachable]; + } + + bb6: { +- StorageDead(_19); + StorageDead(_18); +- _4 = const (); + goto -> bb7; + } + + bb7: { +- StorageDead(_5); +- StorageDead(_4); + StorageLive(_22); +- StorageLive(_23); +- StorageLive(_24); +- _24 = _2; +- StorageLive(_25); +- _25 = _3; +- _23 = Add(move _24, move _25); +- StorageDead(_25); +- StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb8, unwind unreachable]; ++ _23 = Add(_2, _3); ++ _22 = opaque::(_23) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_23); + StorageDead(_22); +- StorageLive(_26); +- _26 = _1; +- switchInt(move _26) -> [0: bb11, otherwise: bb9]; ++ switchInt(_1) -> [0: bb11, otherwise: bb9]; + } + + bb9: { + StorageLive(_27); +- StorageLive(_28); +- StorageLive(_29); +- _29 = _2; +- StorageLive(_30); +- _30 = _3; +- _28 = Add(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); +- _27 = opaque::(move _28) -> [return: bb10, unwind unreachable]; ++ _27 = opaque::(_23) -> [return: bb10, unwind unreachable]; + } + + bb10: { +- StorageDead(_28); + StorageDead(_27); + _0 = const (); + goto -> bb13; + } + + bb11: { + StorageLive(_31); +- StorageLive(_32); +- StorageLive(_33); +- _33 = _2; +- StorageLive(_34); +- _34 = _3; +- _32 = Add(move _33, move _34); +- StorageDead(_34); +- StorageDead(_33); +- _31 = opaque::(move _32) -> [return: bb12, unwind unreachable]; ++ _31 = opaque::(_23) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + goto -> bb13; + } + + bb13: { +- StorageDead(_26); + return; + } + } + diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..0199f2720a989 --- /dev/null +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff @@ -0,0 +1,198 @@ +- // MIR for `multiple_branches` before GVN ++ // MIR for `multiple_branches` after GVN + + fn multiple_branches(_1: bool, _2: u8, _3: u8) -> () { + debug t => _1; + debug x => _2; + debug y => _3; + let mut _0: (); + let _4: (); + let mut _5: bool; + let _6: (); + let mut _7: u8; + let mut _8: u8; + let mut _9: u8; + let _10: (); + let mut _11: u8; + let mut _12: u8; + let mut _13: u8; + let _14: (); + let mut _15: u8; + let mut _16: u8; + let mut _17: u8; + let _18: (); + let mut _19: u8; + let mut _20: u8; + let mut _21: u8; + let _22: (); + let mut _23: u8; + let mut _24: u8; + let mut _25: u8; + let mut _26: bool; + let _27: (); + let mut _28: u8; + let mut _29: u8; + let mut _30: u8; + let _31: (); + let mut _32: u8; + let mut _33: u8; + let mut _34: u8; + + bb0: { +- StorageLive(_4); +- StorageLive(_5); +- _5 = _1; +- switchInt(move _5) -> [0: bb4, otherwise: bb1]; ++ switchInt(_1) -> [0: bb4, otherwise: bb1]; + } + + bb1: { + StorageLive(_6); +- StorageLive(_7); +- StorageLive(_8); +- _8 = _2; +- StorageLive(_9); +- _9 = _3; +- _7 = Add(move _8, move _9); +- StorageDead(_9); +- StorageDead(_8); +- _6 = opaque::(move _7) -> [return: bb2, unwind continue]; ++ _7 = Add(_2, _3); ++ _6 = opaque::(_7) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_7); + StorageDead(_6); + StorageLive(_10); +- StorageLive(_11); +- StorageLive(_12); +- _12 = _2; +- StorageLive(_13); +- _13 = _3; +- _11 = Add(move _12, move _13); +- StorageDead(_13); +- StorageDead(_12); +- _10 = opaque::(move _11) -> [return: bb3, unwind continue]; ++ _10 = opaque::(_7) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_11); + StorageDead(_10); +- _4 = const (); + goto -> bb7; + } + + bb4: { + StorageLive(_14); +- StorageLive(_15); +- StorageLive(_16); +- _16 = _2; +- StorageLive(_17); +- _17 = _3; +- _15 = Add(move _16, move _17); +- StorageDead(_17); +- StorageDead(_16); +- _14 = opaque::(move _15) -> [return: bb5, unwind continue]; ++ _15 = Add(_2, _3); ++ _14 = opaque::(_15) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_15); + StorageDead(_14); + StorageLive(_18); +- StorageLive(_19); +- StorageLive(_20); +- _20 = _2; +- StorageLive(_21); +- _21 = _3; +- _19 = Add(move _20, move _21); +- StorageDead(_21); +- StorageDead(_20); +- _18 = opaque::(move _19) -> [return: bb6, unwind continue]; ++ _18 = opaque::(_15) -> [return: bb6, unwind continue]; + } + + bb6: { +- StorageDead(_19); + StorageDead(_18); +- _4 = const (); + goto -> bb7; + } + + bb7: { +- StorageDead(_5); +- StorageDead(_4); + StorageLive(_22); +- StorageLive(_23); +- StorageLive(_24); +- _24 = _2; +- StorageLive(_25); +- _25 = _3; +- _23 = Add(move _24, move _25); +- StorageDead(_25); +- StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb8, unwind continue]; ++ _23 = Add(_2, _3); ++ _22 = opaque::(_23) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_23); + StorageDead(_22); +- StorageLive(_26); +- _26 = _1; +- switchInt(move _26) -> [0: bb11, otherwise: bb9]; ++ switchInt(_1) -> [0: bb11, otherwise: bb9]; + } + + bb9: { + StorageLive(_27); +- StorageLive(_28); +- StorageLive(_29); +- _29 = _2; +- StorageLive(_30); +- _30 = _3; +- _28 = Add(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); +- _27 = opaque::(move _28) -> [return: bb10, unwind continue]; ++ _27 = opaque::(_23) -> [return: bb10, unwind continue]; + } + + bb10: { +- StorageDead(_28); + StorageDead(_27); + _0 = const (); + goto -> bb13; + } + + bb11: { + StorageLive(_31); +- StorageLive(_32); +- StorageLive(_33); +- _33 = _2; +- StorageLive(_34); +- _34 = _3; +- _32 = Add(move _33, move _34); +- StorageDead(_34); +- StorageDead(_33); +- _31 = opaque::(move _32) -> [return: bb12, unwind continue]; ++ _31 = opaque::(_23) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + goto -> bb13; + } + + bb13: { +- StorageDead(_26); + return; + } + } + diff --git a/tests/mir-opt/gvn.references.GVN.panic-abort.diff b/tests/mir-opt/gvn.references.GVN.panic-abort.diff new file mode 100644 index 0000000000000..b7ad4ab1fd3d8 --- /dev/null +++ b/tests/mir-opt/gvn.references.GVN.panic-abort.diff @@ -0,0 +1,105 @@ +- // MIR for `references` before GVN ++ // MIR for `references` after GVN + + fn references(_1: impl Sized) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: &impl Sized; + let _4: (); + let mut _5: &impl Sized; + let _6: (); + let mut _7: &mut impl Sized; + let _8: (); + let mut _9: &mut impl Sized; + let _10: (); + let mut _11: *const impl Sized; + let _12: (); + let mut _13: *const impl Sized; + let _14: (); + let mut _15: *mut impl Sized; + let _16: (); + let mut _17: *mut impl Sized; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = &_1; + _2 = opaque::<&impl Sized>(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = &_1; + _4 = opaque::<&impl Sized>(move _5) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = &mut _1; + _6 = opaque::<&mut impl Sized>(move _7) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = &mut _1; + _8 = opaque::<&mut impl Sized>(move _9) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = &raw const _1; + _10 = opaque::<*const impl Sized>(move _11) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = &raw const _1; + _12 = opaque::<*const impl Sized>(move _13) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = &raw mut _1; + _14 = opaque::<*mut impl Sized>(move _15) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = &raw mut _1; + _16 = opaque::<*mut impl Sized>(move _17) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + drop(_1) -> [return: bb9, unwind unreachable]; + } + + bb9: { + return; + } + } + diff --git a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..08ed4c629a6dd --- /dev/null +++ b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff @@ -0,0 +1,113 @@ +- // MIR for `references` before GVN ++ // MIR for `references` after GVN + + fn references(_1: impl Sized) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: &impl Sized; + let _4: (); + let mut _5: &impl Sized; + let _6: (); + let mut _7: &mut impl Sized; + let _8: (); + let mut _9: &mut impl Sized; + let _10: (); + let mut _11: *const impl Sized; + let _12: (); + let mut _13: *const impl Sized; + let _14: (); + let mut _15: *mut impl Sized; + let _16: (); + let mut _17: *mut impl Sized; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = &_1; + _2 = opaque::<&impl Sized>(move _3) -> [return: bb1, unwind: bb10]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = &_1; + _4 = opaque::<&impl Sized>(move _5) -> [return: bb2, unwind: bb10]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = &mut _1; + _6 = opaque::<&mut impl Sized>(move _7) -> [return: bb3, unwind: bb10]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = &mut _1; + _8 = opaque::<&mut impl Sized>(move _9) -> [return: bb4, unwind: bb10]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = &raw const _1; + _10 = opaque::<*const impl Sized>(move _11) -> [return: bb5, unwind: bb10]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = &raw const _1; + _12 = opaque::<*const impl Sized>(move _13) -> [return: bb6, unwind: bb10]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = &raw mut _1; + _14 = opaque::<*mut impl Sized>(move _15) -> [return: bb7, unwind: bb10]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = &raw mut _1; + _16 = opaque::<*mut impl Sized>(move _17) -> [return: bb8, unwind: bb10]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + drop(_1) -> [return: bb9, unwind: bb11]; + } + + bb9: { + return; + } + + bb10 (cleanup): { + drop(_1) -> [return: bb11, unwind terminate(cleanup)]; + } + + bb11 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff new file mode 100644 index 0000000000000..4c29523d6b282 --- /dev/null +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -0,0 +1,76 @@ +- // MIR for `repeated_index` before GVN ++ // MIR for `repeated_index` after GVN + + fn repeated_index(_1: T, _2: usize) -> () { + debug x => _1; + debug idx => _2; + let mut _0: (); + let _3: [T; N]; + let mut _4: T; + let _5: (); + let mut _6: T; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let _10: (); + let mut _11: T; + let _12: usize; + let mut _13: usize; + let mut _14: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = [move _4; N]; +- StorageDead(_4); ++ _3 = [_1; N]; + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 0_usize; + _8 = Len(_3); +- _9 = Lt(_7, _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable]; ++ _9 = Lt(const 0_usize, _8); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _6 = _3[_7]; + _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_7); + StorageDead(_5); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + _12 = _2; +- _13 = Len(_3); +- _14 = Lt(_12, _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable]; ++ _14 = Lt(_2, _8); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind unreachable]; + } + + bb3: { + _11 = _3[_12]; + _10 = opaque::(move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_12); + StorageDead(_10); + _0 = const (); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..e44f54cf3cf3c --- /dev/null +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -0,0 +1,76 @@ +- // MIR for `repeated_index` before GVN ++ // MIR for `repeated_index` after GVN + + fn repeated_index(_1: T, _2: usize) -> () { + debug x => _1; + debug idx => _2; + let mut _0: (); + let _3: [T; N]; + let mut _4: T; + let _5: (); + let mut _6: T; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let _10: (); + let mut _11: T; + let _12: usize; + let mut _13: usize; + let mut _14: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = [move _4; N]; +- StorageDead(_4); ++ _3 = [_1; N]; + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 0_usize; + _8 = Len(_3); +- _9 = Lt(_7, _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue]; ++ _9 = Lt(const 0_usize, _8); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind continue]; + } + + bb1: { + _6 = _3[_7]; + _5 = opaque::(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_7); + StorageDead(_5); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + _12 = _2; +- _13 = Len(_3); +- _14 = Lt(_12, _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue]; ++ _14 = Lt(_2, _8); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind continue]; + } + + bb3: { + _11 = _3[_12]; + _10 = opaque::(move _11) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_11); + StorageDead(_12); + StorageDead(_10); + _0 = const (); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs new file mode 100644 index 0000000000000..a85e2ae368b41 --- /dev/null +++ b/tests/mir-opt/gvn.rs @@ -0,0 +1,253 @@ +// unit-test: GVN +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(raw_ref_op)] +#![feature(rustc_attrs)] +#![allow(unconditional_panic)] + +struct S(T); + +fn subexpression_elimination(x: u64, y: u64, mut z: u64) { + opaque(x + y); + opaque(x * y); + opaque(x - y); + opaque(x / y); + opaque(x % y); + opaque(x & y); + opaque(x | y); + opaque(x ^ y); + opaque(x << y); + opaque(x >> y); + opaque(x as u32); + opaque(x as f32); + opaque(S(x)); + opaque(S(x).0); + + // Those are duplicates to substitute somehow. + opaque((x + y) + z); + opaque((x * y) + z); + opaque((x - y) + z); + opaque((x / y) + z); + opaque((x % y) + z); + opaque((x & y) + z); + opaque((x | y) + z); + opaque((x ^ y) + z); + opaque((x << y) + z); + opaque((x >> y) + z); + opaque(S(x)); + opaque(S(x).0); + + // We can substitute through an immutable reference too. + let a = &z; + opaque(*a + x); + opaque(*a + x); + + // But not through a mutable reference or a pointer. + let b = &mut z; + opaque(*b + x); + opaque(*b + x); + unsafe { + let c = &raw const z; + opaque(*c + x); + opaque(*c + x); + let d = &raw mut z; + opaque(*d + x); + opaque(*d + x); + } + + // We can substitute again, but not with the earlier computations. + // Important: `e` is not `a`! + let e = &z; + opaque(*e + x); + opaque(*e + x); + +} + +fn wrap_unwrap(x: T) -> T { + match Some(x) { + Some(y) => y, + None => panic!(), + } +} + +fn repeated_index(x: T, idx: usize) { + let a = [x; N]; + opaque(a[0]); + opaque(a[idx]); +} + +fn arithmetic(x: u64) { + opaque(x + 0); + opaque(x - 0); + opaque(x * 0); + opaque(x * 1); + opaque(x / 0); + opaque(x / 1); + opaque(0 / x); + opaque(1 / x); + opaque(x % 0); + opaque(x % 1); + opaque(0 % x); + opaque(1 % x); + opaque(x & 0); + opaque(x | 0); + opaque(x ^ 0); + opaque(x >> 0); + opaque(x << 0); +} + +#[rustc_inherit_overflow_checks] +fn arithmetic_checked(x: u64) { + opaque(x + 0); + opaque(x - 0); + opaque(x * 0); + opaque(x * 1); + opaque(x / 0); + opaque(x / 1); + opaque(0 / x); + opaque(1 / x); + opaque(x % 0); + opaque(x % 1); + opaque(0 % x); + opaque(1 % x); + opaque(x & 0); + opaque(x | 0); + opaque(x ^ 0); + opaque(x >> 0); + opaque(x << 0); +} + +fn arithmetic_float(x: f64) { + opaque(x + 0.); + opaque(x - 0.); + opaque(x * 0.); + opaque(x / 0.); + opaque(0. / x); + opaque(x % 0.); + opaque(0. % x); + // Those are not simplifiable to `true`/`false`, thanks to NaNs. + opaque(x == x); + opaque(x != x); +} + +fn cast() { + let i = 1_i64; + let u = 1_u64; + let f = 1_f64; + opaque(i as u8); + opaque(i as u16); + opaque(i as u32); + opaque(i as u64); + opaque(i as i8); + opaque(i as i16); + opaque(i as i32); + opaque(i as i64); + opaque(i as f32); + opaque(i as f64); + opaque(u as u8); + opaque(u as u16); + opaque(u as u32); + opaque(u as u64); + opaque(u as i8); + opaque(u as i16); + opaque(u as i32); + opaque(u as i64); + opaque(u as f32); + opaque(u as f64); + opaque(f as u8); + opaque(f as u16); + opaque(f as u32); + opaque(f as u64); + opaque(f as i8); + opaque(f as i16); + opaque(f as i32); + opaque(f as i64); + opaque(f as f32); + opaque(f as f64); +} + +fn multiple_branches(t: bool, x: u8, y: u8) { + if t { + opaque(x + y); // a + opaque(x + y); // should reuse a + } else { + opaque(x + y); // b + opaque(x + y); // shoud reuse b + } + opaque(x + y); // c + if t { + opaque(x + y); // should reuse c + } else { + opaque(x + y); // should reuse c + } +} + +fn references(mut x: impl Sized) { + opaque(&x); + opaque(&x); // should not reuse a + opaque(&mut x); + opaque(&mut x); // should not reuse a + opaque(&raw const x); + opaque(&raw const x); // should not reuse a + opaque(&raw mut x); + opaque(&raw mut x); // should not reuse a +} + +fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { + opaque(*t); + opaque(*t); // this cannot reuse a, as x is &mut. + let z = &raw const *t; + unsafe { opaque(*z) }; + unsafe { opaque(*z) }; // this cannot reuse a, as x is *const. + let z = &raw mut *t; + unsafe { opaque(*z) }; + unsafe { opaque(*z) }; // this cannot reuse a, as x is *mut. + let z = &*t; + opaque(*z); + opaque(*z); // this can reuse, as `z` is immutable ref, Freeze and Copy. + opaque(&*z); // but not for a reborrow. + opaque(*u); + opaque(*u); // this cannot reuse, as `z` is not Freeze. + opaque(s.0); + opaque(s.0); // *s is not Copy, by (*s).0 is, so we can reuse. +} + +fn slices() { + let s = "my favourite slice"; // This is a `Const::Slice` in MIR. + opaque(s); + let t = s; // This should be the same pointer, so cannot be a `Const::Slice`. + opaque(t); + assert_eq!(s.as_ptr(), t.as_ptr()); + let u = unsafe { std::mem::transmute::<&str, &[u8]>(s) }; + opaque(u); + assert_eq!(s.as_ptr(), u.as_ptr()); +} + +fn main() { + subexpression_elimination(2, 4, 5); + wrap_unwrap(5); + repeated_index::(5, 3); + arithmetic(5); + arithmetic_checked(5); + arithmetic_float(5.); + cast(); + multiple_branches(true, 5, 9); + references(5); + dereferences(&mut 5, &6, &S(7)); + slices(); +} + +#[inline(never)] +fn opaque(_: impl Sized) {} + +// EMIT_MIR gvn.subexpression_elimination.GVN.diff +// EMIT_MIR gvn.wrap_unwrap.GVN.diff +// EMIT_MIR gvn.repeated_index.GVN.diff +// EMIT_MIR gvn.arithmetic.GVN.diff +// EMIT_MIR gvn.arithmetic_checked.GVN.diff +// EMIT_MIR gvn.arithmetic_float.GVN.diff +// EMIT_MIR gvn.cast.GVN.diff +// EMIT_MIR gvn.multiple_branches.GVN.diff +// EMIT_MIR gvn.references.GVN.diff +// EMIT_MIR gvn.dereferences.GVN.diff +// EMIT_MIR gvn.slices.GVN.diff diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff new file mode 100644 index 0000000000000..de3d28d057594 --- /dev/null +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -0,0 +1,275 @@ +- // MIR for `slices` before GVN ++ // MIR for `slices` after GVN + + fn slices() -> () { + let mut _0: (); + let _1: &str; + let _2: (); + let mut _3: &str; + let _5: (); + let mut _6: &str; + let _7: (); + let mut _8: (&*const u8, &*const u8); + let mut _9: &*const u8; + let _10: *const u8; + let mut _11: &str; + let mut _12: &*const u8; + let _13: *const u8; + let mut _14: &str; + let mut _17: bool; + let mut _18: *const u8; + let mut _19: *const u8; + let mut _20: !; + let _22: !; + let mut _23: core::panicking::AssertKind; + let mut _24: &*const u8; + let _25: &*const u8; + let mut _26: &*const u8; + let _27: &*const u8; + let mut _28: std::option::Option>; + let mut _30: &str; + let _31: (); + let mut _32: &[u8]; + let _33: (); + let mut _34: (&*const u8, &*const u8); + let mut _35: &*const u8; + let _36: *const u8; + let mut _37: &str; + let mut _38: &*const u8; + let _39: *const u8; + let mut _40: &[u8]; + let mut _43: bool; + let mut _44: *const u8; + let mut _45: *const u8; + let mut _46: !; + let _48: !; + let mut _49: core::panicking::AssertKind; + let mut _50: &*const u8; + let _51: &*const u8; + let mut _52: &*const u8; + let _53: &*const u8; + let mut _54: std::option::Option>; + scope 1 { + debug s => _1; + let _4: &str; + scope 2 { + debug t => _4; + let _15: &*const u8; + let _16: &*const u8; + let _29: &[u8]; + scope 3 { + debug left_val => _15; + debug right_val => _16; + let _21: core::panicking::AssertKind; + scope 4 { + debug kind => _21; + } + } + scope 5 { + debug u => _29; + let _41: &*const u8; + let _42: &*const u8; + scope 7 { + debug left_val => _41; + debug right_val => _42; + let _47: core::panicking::AssertKind; + scope 8 { + debug kind => _47; + } + } + } + scope 6 { + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const "my favourite slice"; + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = opaque::<&str>(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::<&str>(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + _4 = _1; + StorageLive(_5); +- StorageLive(_6); +- _6 = _4; +- _5 = opaque::<&str>(move _6) -> [return: bb2, unwind unreachable]; ++ _5 = opaque::<&str>(_1) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_6); + StorageDead(_5); +- StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = &(*_1); + _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_11); + _9 = &_10; + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = &(*_4); + _13 = core::str::::as_ptr(move _14) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_14); + _12 = &_13; + _8 = (move _9, move _12); + StorageDead(_12); + StorageDead(_9); + StorageLive(_15); + _15 = (_8.0: &*const u8); + StorageLive(_16); + _16 = (_8.1: &*const u8); + StorageLive(_17); + StorageLive(_18); + _18 = (*_15); + StorageLive(_19); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb6, otherwise: bb5]; + } + + bb5: { + StorageDead(_19); + StorageDead(_18); +- _7 = const (); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + StorageDead(_10); + StorageDead(_8); +- StorageDead(_7); +- StorageLive(_29); + StorageLive(_30); + _30 = &(*_1); + _29 = move _30 as &[u8] (Transmute); + StorageDead(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _29; +- _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind unreachable]; ++ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind unreachable]; + } + + bb6: { + StorageDead(_19); + StorageDead(_18); +- StorageLive(_21); + _21 = core::panicking::AssertKind::Eq; + StorageLive(_22); +- StorageLive(_23); +- _23 = move _21; + StorageLive(_24); + StorageLive(_25); + _25 = &(*_15); + _24 = &(*_25); + StorageLive(_26); + StorageLive(_27); + _27 = &(*_16); + _26 = &(*_27); + StorageLive(_28); + _28 = Option::>::None; +- _22 = core::panicking::assert_failed::<*const u8, *const u8>(move _23, move _24, move _26, move _28) -> unwind unreachable; ++ _22 = core::panicking::assert_failed::<*const u8, *const u8>(_21, move _24, move _26, move _28) -> unwind unreachable; + } + + bb7: { +- StorageDead(_32); + StorageDead(_31); +- StorageLive(_33); + StorageLive(_34); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + _37 = &(*_1); + _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_37); + _35 = &_36; + StorageLive(_38); + StorageLive(_39); + StorageLive(_40); + _40 = &(*_29); + _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_40); + _38 = &_39; + _34 = (move _35, move _38); + StorageDead(_38); + StorageDead(_35); + StorageLive(_41); + _41 = (_34.0: &*const u8); + StorageLive(_42); + _42 = (_34.1: &*const u8); + StorageLive(_43); + StorageLive(_44); + _44 = (*_41); + StorageLive(_45); + _45 = (*_42); + _43 = Eq(move _44, move _45); + switchInt(move _43) -> [0: bb11, otherwise: bb10]; + } + + bb10: { + StorageDead(_45); + StorageDead(_44); +- _33 = const (); + StorageDead(_43); + StorageDead(_42); + StorageDead(_41); + StorageDead(_39); + StorageDead(_36); + StorageDead(_34); +- StorageDead(_33); + _0 = const (); +- StorageDead(_29); + StorageDead(_4); +- StorageDead(_1); + return; + } + + bb11: { + StorageDead(_45); + StorageDead(_44); +- StorageLive(_47); + _47 = core::panicking::AssertKind::Eq; + StorageLive(_48); +- StorageLive(_49); +- _49 = move _47; + StorageLive(_50); + StorageLive(_51); + _51 = &(*_41); + _50 = &(*_51); + StorageLive(_52); + StorageLive(_53); + _53 = &(*_42); + _52 = &(*_53); + StorageLive(_54); + _54 = Option::>::None; +- _48 = core::panicking::assert_failed::<*const u8, *const u8>(move _49, move _50, move _52, move _54) -> unwind unreachable; ++ _48 = core::panicking::assert_failed::<*const u8, *const u8>(_47, move _50, move _52, move _54) -> unwind unreachable; + } + } + diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..f22bb25436f05 --- /dev/null +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -0,0 +1,275 @@ +- // MIR for `slices` before GVN ++ // MIR for `slices` after GVN + + fn slices() -> () { + let mut _0: (); + let _1: &str; + let _2: (); + let mut _3: &str; + let _5: (); + let mut _6: &str; + let _7: (); + let mut _8: (&*const u8, &*const u8); + let mut _9: &*const u8; + let _10: *const u8; + let mut _11: &str; + let mut _12: &*const u8; + let _13: *const u8; + let mut _14: &str; + let mut _17: bool; + let mut _18: *const u8; + let mut _19: *const u8; + let mut _20: !; + let _22: !; + let mut _23: core::panicking::AssertKind; + let mut _24: &*const u8; + let _25: &*const u8; + let mut _26: &*const u8; + let _27: &*const u8; + let mut _28: std::option::Option>; + let mut _30: &str; + let _31: (); + let mut _32: &[u8]; + let _33: (); + let mut _34: (&*const u8, &*const u8); + let mut _35: &*const u8; + let _36: *const u8; + let mut _37: &str; + let mut _38: &*const u8; + let _39: *const u8; + let mut _40: &[u8]; + let mut _43: bool; + let mut _44: *const u8; + let mut _45: *const u8; + let mut _46: !; + let _48: !; + let mut _49: core::panicking::AssertKind; + let mut _50: &*const u8; + let _51: &*const u8; + let mut _52: &*const u8; + let _53: &*const u8; + let mut _54: std::option::Option>; + scope 1 { + debug s => _1; + let _4: &str; + scope 2 { + debug t => _4; + let _15: &*const u8; + let _16: &*const u8; + let _29: &[u8]; + scope 3 { + debug left_val => _15; + debug right_val => _16; + let _21: core::panicking::AssertKind; + scope 4 { + debug kind => _21; + } + } + scope 5 { + debug u => _29; + let _41: &*const u8; + let _42: &*const u8; + scope 7 { + debug left_val => _41; + debug right_val => _42; + let _47: core::panicking::AssertKind; + scope 8 { + debug kind => _47; + } + } + } + scope 6 { + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const "my favourite slice"; + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = opaque::<&str>(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::<&str>(_1) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + _4 = _1; + StorageLive(_5); +- StorageLive(_6); +- _6 = _4; +- _5 = opaque::<&str>(move _6) -> [return: bb2, unwind continue]; ++ _5 = opaque::<&str>(_1) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_6); + StorageDead(_5); +- StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = &(*_1); + _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_11); + _9 = &_10; + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = &(*_4); + _13 = core::str::::as_ptr(move _14) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_14); + _12 = &_13; + _8 = (move _9, move _12); + StorageDead(_12); + StorageDead(_9); + StorageLive(_15); + _15 = (_8.0: &*const u8); + StorageLive(_16); + _16 = (_8.1: &*const u8); + StorageLive(_17); + StorageLive(_18); + _18 = (*_15); + StorageLive(_19); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb6, otherwise: bb5]; + } + + bb5: { + StorageDead(_19); + StorageDead(_18); +- _7 = const (); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + StorageDead(_10); + StorageDead(_8); +- StorageDead(_7); +- StorageLive(_29); + StorageLive(_30); + _30 = &(*_1); + _29 = move _30 as &[u8] (Transmute); + StorageDead(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _29; +- _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind continue]; ++ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind continue]; + } + + bb6: { + StorageDead(_19); + StorageDead(_18); +- StorageLive(_21); + _21 = core::panicking::AssertKind::Eq; + StorageLive(_22); +- StorageLive(_23); +- _23 = move _21; + StorageLive(_24); + StorageLive(_25); + _25 = &(*_15); + _24 = &(*_25); + StorageLive(_26); + StorageLive(_27); + _27 = &(*_16); + _26 = &(*_27); + StorageLive(_28); + _28 = Option::>::None; +- _22 = core::panicking::assert_failed::<*const u8, *const u8>(move _23, move _24, move _26, move _28) -> unwind continue; ++ _22 = core::panicking::assert_failed::<*const u8, *const u8>(_21, move _24, move _26, move _28) -> unwind continue; + } + + bb7: { +- StorageDead(_32); + StorageDead(_31); +- StorageLive(_33); + StorageLive(_34); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + _37 = &(*_1); + _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_37); + _35 = &_36; + StorageLive(_38); + StorageLive(_39); + StorageLive(_40); + _40 = &(*_29); + _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_40); + _38 = &_39; + _34 = (move _35, move _38); + StorageDead(_38); + StorageDead(_35); + StorageLive(_41); + _41 = (_34.0: &*const u8); + StorageLive(_42); + _42 = (_34.1: &*const u8); + StorageLive(_43); + StorageLive(_44); + _44 = (*_41); + StorageLive(_45); + _45 = (*_42); + _43 = Eq(move _44, move _45); + switchInt(move _43) -> [0: bb11, otherwise: bb10]; + } + + bb10: { + StorageDead(_45); + StorageDead(_44); +- _33 = const (); + StorageDead(_43); + StorageDead(_42); + StorageDead(_41); + StorageDead(_39); + StorageDead(_36); + StorageDead(_34); +- StorageDead(_33); + _0 = const (); +- StorageDead(_29); + StorageDead(_4); +- StorageDead(_1); + return; + } + + bb11: { + StorageDead(_45); + StorageDead(_44); +- StorageLive(_47); + _47 = core::panicking::AssertKind::Eq; + StorageLive(_48); +- StorageLive(_49); +- _49 = move _47; + StorageLive(_50); + StorageLive(_51); + _51 = &(*_41); + _50 = &(*_51); + StorageLive(_52); + StorageLive(_53); + _53 = &(*_42); + _52 = &(*_53); + StorageLive(_54); + _54 = Option::>::None; +- _48 = core::panicking::assert_failed::<*const u8, *const u8>(move _49, move _50, move _52, move _54) -> unwind continue; ++ _48 = core::panicking::assert_failed::<*const u8, *const u8>(_47, move _50, move _52, move _54) -> unwind continue; + } + } + diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff new file mode 100644 index 0000000000000..bf866e2f4d22f --- /dev/null +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -0,0 +1,883 @@ +- // MIR for `subexpression_elimination` before GVN ++ // MIR for `subexpression_elimination` after GVN + + fn subexpression_elimination(_1: u64, _2: u64, _3: u64) -> () { + debug x => _1; + debug y => _2; + debug z => _3; + let mut _0: (); + let _4: (); + let mut _5: u64; + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let mut _11: u64; + let _12: (); + let mut _13: u64; + let mut _14: u64; + let mut _15: u64; + let _16: (); + let mut _17: u64; + let mut _18: u64; + let mut _19: u64; + let mut _20: bool; + let _21: (); + let mut _22: u64; + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: u64; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: u64; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: u64; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: u64; + let _46: (); + let mut _47: u32; + let mut _48: u64; + let _49: (); + let mut _50: f32; + let mut _51: u64; + let _52: (); + let mut _53: S; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: S; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u64; + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let mut _69: u64; + let mut _70: u64; + let _71: (); + let mut _72: u64; + let mut _73: u64; + let mut _74: u64; + let mut _75: u64; + let mut _76: u64; + let _77: (); + let mut _78: u64; + let mut _79: u64; + let mut _80: u64; + let mut _81: u64; + let mut _82: bool; + let mut _83: u64; + let _84: (); + let mut _85: u64; + let mut _86: u64; + let mut _87: u64; + let mut _88: u64; + let mut _89: bool; + let mut _90: u64; + let _91: (); + let mut _92: u64; + let mut _93: u64; + let mut _94: u64; + let mut _95: u64; + let mut _96: u64; + let _97: (); + let mut _98: u64; + let mut _99: u64; + let mut _100: u64; + let mut _101: u64; + let mut _102: u64; + let _103: (); + let mut _104: u64; + let mut _105: u64; + let mut _106: u64; + let mut _107: u64; + let mut _108: u64; + let _109: (); + let mut _110: u64; + let mut _111: u64; + let mut _112: u64; + let mut _113: u64; + let mut _114: u64; + let _115: (); + let mut _116: u64; + let mut _117: u64; + let mut _118: u64; + let mut _119: u64; + let mut _120: u64; + let _121: (); + let mut _122: S; + let mut _123: u64; + let _124: (); + let mut _125: u64; + let mut _126: S; + let mut _127: u64; + let _128: &u64; + let _129: (); + let mut _130: u64; + let mut _131: u64; + let mut _132: u64; + let _133: (); + let mut _134: u64; + let mut _135: u64; + let mut _136: u64; + let _138: (); + let mut _139: u64; + let mut _140: u64; + let mut _141: u64; + let _142: (); + let mut _143: u64; + let mut _144: u64; + let mut _145: u64; + let _146: (); + let _148: (); + let mut _149: u64; + let mut _150: u64; + let mut _151: u64; + let _152: (); + let mut _153: u64; + let mut _154: u64; + let mut _155: u64; + let _157: (); + let mut _158: u64; + let mut _159: u64; + let mut _160: u64; + let _161: (); + let mut _162: u64; + let mut _163: u64; + let mut _164: u64; + let _166: (); + let mut _167: u64; + let mut _168: u64; + let mut _169: u64; + let _170: (); + let mut _171: u64; + let mut _172: u64; + let mut _173: u64; + scope 1 { + debug a => _128; + let _137: &mut u64; + scope 2 { + debug b => _137; + let _165: &u64; + scope 3 { + let _147: *const u64; + scope 4 { + debug c => _147; + let _156: *mut u64; + scope 5 { + debug d => _156; + } + } + } + scope 6 { + debug e => _165; + } + } + } + + bb0: { + StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- StorageLive(_7); +- _7 = _2; +- _5 = Add(move _6, move _7); +- StorageDead(_7); +- StorageDead(_6); +- _4 = opaque::(move _5) -> [return: bb1, unwind unreachable]; ++ _5 = Add(_1, _2); ++ _4 = opaque::(_5) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_5); + StorageDead(_4); + StorageLive(_8); +- StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- StorageLive(_11); +- _11 = _2; +- _9 = Mul(move _10, move _11); +- StorageDead(_11); +- StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind unreachable]; ++ _9 = Mul(_1, _2); ++ _8 = opaque::(_9) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); +- StorageLive(_14); +- _14 = _1; +- StorageLive(_15); +- _15 = _2; +- _13 = Sub(move _14, move _15); +- StorageDead(_15); +- StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind unreachable]; ++ _13 = Sub(_1, _2); ++ _12 = opaque::(_13) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_16); +- StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- StorageLive(_19); +- _19 = _2; +- _20 = Eq(_19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind unreachable]; ++ _20 = Eq(_2, const 0_u64); ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind unreachable]; + } + + bb4: { +- _17 = Div(move _18, move _19); +- StorageDead(_19); +- StorageDead(_18); +- _16 = opaque::(move _17) -> [return: bb5, unwind unreachable]; ++ _17 = Div(_1, _2); ++ _16 = opaque::(_17) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_17); + StorageDead(_16); + StorageLive(_21); +- StorageLive(_22); +- StorageLive(_23); +- _23 = _1; +- StorageLive(_24); +- _24 = _2; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind unreachable]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind unreachable]; + } + + bb6: { +- _22 = Rem(move _23, move _24); +- StorageDead(_24); +- StorageDead(_23); +- _21 = opaque::(move _22) -> [return: bb7, unwind unreachable]; ++ _22 = Rem(_1, _2); ++ _21 = opaque::(_22) -> [return: bb7, unwind unreachable]; + } + + bb7: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_26); +- StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- StorageLive(_29); +- _29 = _2; +- _27 = BitAnd(move _28, move _29); +- StorageDead(_29); +- StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb8, unwind unreachable]; ++ _27 = BitAnd(_1, _2); ++ _26 = opaque::(_27) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_27); + StorageDead(_26); + StorageLive(_30); +- StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- StorageLive(_33); +- _33 = _2; +- _31 = BitOr(move _32, move _33); +- StorageDead(_33); +- StorageDead(_32); +- _30 = opaque::(move _31) -> [return: bb9, unwind unreachable]; ++ _31 = BitOr(_1, _2); ++ _30 = opaque::(_31) -> [return: bb9, unwind unreachable]; + } + + bb9: { +- StorageDead(_31); + StorageDead(_30); + StorageLive(_34); +- StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- StorageLive(_37); +- _37 = _2; +- _35 = BitXor(move _36, move _37); +- StorageDead(_37); +- StorageDead(_36); +- _34 = opaque::(move _35) -> [return: bb10, unwind unreachable]; ++ _35 = BitXor(_1, _2); ++ _34 = opaque::(_35) -> [return: bb10, unwind unreachable]; + } + + bb10: { +- StorageDead(_35); + StorageDead(_34); + StorageLive(_38); +- StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- StorageLive(_41); +- _41 = _2; +- _39 = Shl(move _40, move _41); +- StorageDead(_41); +- StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb11, unwind unreachable]; ++ _39 = Shl(_1, _2); ++ _38 = opaque::(_39) -> [return: bb11, unwind unreachable]; + } + + bb11: { +- StorageDead(_39); + StorageDead(_38); + StorageLive(_42); +- StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- StorageLive(_45); +- _45 = _2; +- _43 = Shr(move _44, move _45); +- StorageDead(_45); +- StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb12, unwind unreachable]; ++ _43 = Shr(_1, _2); ++ _42 = opaque::(_43) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = move _48 as u32 (IntToInt); +- StorageDead(_48); ++ _47 = _1 as u32 (IntToInt); + _46 = opaque::(move _47) -> [return: bb13, unwind unreachable]; + } + + bb13: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = move _51 as f32 (IntToFloat); +- StorageDead(_51); ++ _50 = _1 as f32 (IntToFloat); + _49 = opaque::(move _50) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); +- StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = S::(move _54); +- StorageDead(_54); +- _52 = opaque::>(move _53) -> [return: bb15, unwind unreachable]; ++ _53 = S::(_1); ++ _52 = opaque::>(_53) -> [return: bb15, unwind unreachable]; + } + + bb15: { +- StorageDead(_53); + StorageDead(_52); + StorageLive(_55); +- StorageLive(_56); +- StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = S::(move _58); +- StorageDead(_58); +- _56 = (_57.0: u64); +- _55 = opaque::(move _56) -> [return: bb16, unwind unreachable]; ++ _56 = (_53.0: u64); ++ _55 = opaque::(_56) -> [return: bb16, unwind unreachable]; + } + + bb16: { +- StorageDead(_56); +- StorageDead(_57); + StorageDead(_55); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- StorageLive(_62); +- _62 = _1; +- StorageLive(_63); +- _63 = _2; +- _61 = Add(move _62, move _63); +- StorageDead(_63); +- StorageDead(_62); + StorageLive(_64); + _64 = _3; +- _60 = Add(move _61, move _64); ++ _60 = Add(_5, move _64); + StorageDead(_64); +- StorageDead(_61); + _59 = opaque::(move _60) -> [return: bb17, unwind unreachable]; + } + + bb17: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- StorageLive(_68); +- _68 = _1; +- StorageLive(_69); +- _69 = _2; +- _67 = Mul(move _68, move _69); +- StorageDead(_69); +- StorageDead(_68); + StorageLive(_70); + _70 = _3; +- _66 = Add(move _67, move _70); ++ _66 = Add(_9, move _70); + StorageDead(_70); +- StorageDead(_67); + _65 = opaque::(move _66) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- StorageLive(_74); +- _74 = _1; +- StorageLive(_75); +- _75 = _2; +- _73 = Sub(move _74, move _75); +- StorageDead(_75); +- StorageDead(_74); + StorageLive(_76); + _76 = _3; +- _72 = Add(move _73, move _76); ++ _72 = Add(_13, move _76); + StorageDead(_76); +- StorageDead(_73); + _71 = opaque::(move _72) -> [return: bb19, unwind unreachable]; + } + + bb19: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- StorageLive(_80); +- _80 = _1; +- StorageLive(_81); +- _81 = _2; +- _82 = Eq(_81, const 0_u64); +- assert(!move _82, "attempt to divide `{}` by zero", _80) -> [success: bb20, unwind unreachable]; ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind unreachable]; + } + + bb20: { +- _79 = Div(move _80, move _81); +- StorageDead(_81); +- StorageDead(_80); + StorageLive(_83); + _83 = _3; +- _78 = Add(move _79, move _83); ++ _78 = Add(_17, move _83); + StorageDead(_83); +- StorageDead(_79); + _77 = opaque::(move _78) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_84); + StorageLive(_85); +- StorageLive(_86); +- StorageLive(_87); +- _87 = _1; +- StorageLive(_88); +- _88 = _2; +- _89 = Eq(_88, const 0_u64); +- assert(!move _89, "attempt to calculate the remainder of `{}` with a divisor of zero", _87) -> [success: bb22, unwind unreachable]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind unreachable]; + } + + bb22: { +- _86 = Rem(move _87, move _88); +- StorageDead(_88); +- StorageDead(_87); + StorageLive(_90); + _90 = _3; +- _85 = Add(move _86, move _90); ++ _85 = Add(_22, move _90); + StorageDead(_90); +- StorageDead(_86); + _84 = opaque::(move _85) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_85); + StorageDead(_84); + StorageLive(_91); + StorageLive(_92); +- StorageLive(_93); +- StorageLive(_94); +- _94 = _1; +- StorageLive(_95); +- _95 = _2; +- _93 = BitAnd(move _94, move _95); +- StorageDead(_95); +- StorageDead(_94); + StorageLive(_96); + _96 = _3; +- _92 = Add(move _93, move _96); ++ _92 = Add(_27, move _96); + StorageDead(_96); +- StorageDead(_93); + _91 = opaque::(move _92) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_92); + StorageDead(_91); + StorageLive(_97); + StorageLive(_98); +- StorageLive(_99); +- StorageLive(_100); +- _100 = _1; +- StorageLive(_101); +- _101 = _2; +- _99 = BitOr(move _100, move _101); +- StorageDead(_101); +- StorageDead(_100); + StorageLive(_102); + _102 = _3; +- _98 = Add(move _99, move _102); ++ _98 = Add(_31, move _102); + StorageDead(_102); +- StorageDead(_99); + _97 = opaque::(move _98) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_98); + StorageDead(_97); + StorageLive(_103); + StorageLive(_104); +- StorageLive(_105); +- StorageLive(_106); +- _106 = _1; +- StorageLive(_107); +- _107 = _2; +- _105 = BitXor(move _106, move _107); +- StorageDead(_107); +- StorageDead(_106); + StorageLive(_108); + _108 = _3; +- _104 = Add(move _105, move _108); ++ _104 = Add(_35, move _108); + StorageDead(_108); +- StorageDead(_105); + _103 = opaque::(move _104) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_104); + StorageDead(_103); + StorageLive(_109); + StorageLive(_110); +- StorageLive(_111); +- StorageLive(_112); +- _112 = _1; +- StorageLive(_113); +- _113 = _2; +- _111 = Shl(move _112, move _113); +- StorageDead(_113); +- StorageDead(_112); + StorageLive(_114); + _114 = _3; +- _110 = Add(move _111, move _114); ++ _110 = Add(_39, move _114); + StorageDead(_114); +- StorageDead(_111); + _109 = opaque::(move _110) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_110); + StorageDead(_109); + StorageLive(_115); + StorageLive(_116); +- StorageLive(_117); +- StorageLive(_118); +- _118 = _1; +- StorageLive(_119); +- _119 = _2; +- _117 = Shr(move _118, move _119); +- StorageDead(_119); +- StorageDead(_118); + StorageLive(_120); + _120 = _3; +- _116 = Add(move _117, move _120); ++ _116 = Add(_43, move _120); + StorageDead(_120); +- StorageDead(_117); + _115 = opaque::(move _116) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_116); + StorageDead(_115); + StorageLive(_121); +- StorageLive(_122); +- StorageLive(_123); +- _123 = _1; +- _122 = S::(move _123); +- StorageDead(_123); +- _121 = opaque::>(move _122) -> [return: bb29, unwind unreachable]; ++ _121 = opaque::>(_53) -> [return: bb29, unwind unreachable]; + } + + bb29: { +- StorageDead(_122); + StorageDead(_121); + StorageLive(_124); +- StorageLive(_125); +- StorageLive(_126); +- StorageLive(_127); +- _127 = _1; +- _126 = S::(move _127); +- StorageDead(_127); +- _125 = (_126.0: u64); +- _124 = opaque::(move _125) -> [return: bb30, unwind unreachable]; ++ _124 = opaque::(_56) -> [return: bb30, unwind unreachable]; + } + + bb30: { +- StorageDead(_125); +- StorageDead(_126); + StorageDead(_124); + StorageLive(_128); + _128 = &_3; + StorageLive(_129); +- StorageLive(_130); +- StorageLive(_131); + _131 = (*_128); +- StorageLive(_132); +- _132 = _1; +- _130 = Add(move _131, move _132); +- StorageDead(_132); +- StorageDead(_131); +- _129 = opaque::(move _130) -> [return: bb31, unwind unreachable]; ++ _130 = Add(_131, _1); ++ _129 = opaque::(_130) -> [return: bb31, unwind unreachable]; + } + + bb31: { +- StorageDead(_130); + StorageDead(_129); + StorageLive(_133); +- StorageLive(_134); +- StorageLive(_135); +- _135 = (*_128); +- StorageLive(_136); +- _136 = _1; +- _134 = Add(move _135, move _136); +- StorageDead(_136); +- StorageDead(_135); +- _133 = opaque::(move _134) -> [return: bb32, unwind unreachable]; ++ _133 = opaque::(_130) -> [return: bb32, unwind unreachable]; + } + + bb32: { +- StorageDead(_134); + StorageDead(_133); + StorageLive(_137); + _137 = &mut _3; + StorageLive(_138); + StorageLive(_139); + StorageLive(_140); + _140 = (*_137); +- StorageLive(_141); +- _141 = _1; +- _139 = Add(move _140, move _141); +- StorageDead(_141); ++ _139 = Add(move _140, _1); + StorageDead(_140); + _138 = opaque::(move _139) -> [return: bb33, unwind unreachable]; + } + + bb33: { + StorageDead(_139); + StorageDead(_138); + StorageLive(_142); + StorageLive(_143); + StorageLive(_144); + _144 = (*_137); +- StorageLive(_145); +- _145 = _1; +- _143 = Add(move _144, move _145); +- StorageDead(_145); ++ _143 = Add(move _144, _1); + StorageDead(_144); + _142 = opaque::(move _143) -> [return: bb34, unwind unreachable]; + } + + bb34: { + StorageDead(_143); + StorageDead(_142); +- StorageLive(_146); + StorageLive(_147); + _147 = &raw const _3; + StorageLive(_148); + StorageLive(_149); + StorageLive(_150); + _150 = (*_147); +- StorageLive(_151); +- _151 = _1; +- _149 = Add(move _150, move _151); +- StorageDead(_151); ++ _149 = Add(move _150, _1); + StorageDead(_150); + _148 = opaque::(move _149) -> [return: bb35, unwind unreachable]; + } + + bb35: { + StorageDead(_149); + StorageDead(_148); + StorageLive(_152); + StorageLive(_153); + StorageLive(_154); + _154 = (*_147); +- StorageLive(_155); +- _155 = _1; +- _153 = Add(move _154, move _155); +- StorageDead(_155); ++ _153 = Add(move _154, _1); + StorageDead(_154); + _152 = opaque::(move _153) -> [return: bb36, unwind unreachable]; + } + + bb36: { + StorageDead(_153); + StorageDead(_152); + StorageLive(_156); + _156 = &raw mut _3; + StorageLive(_157); + StorageLive(_158); + StorageLive(_159); + _159 = (*_156); +- StorageLive(_160); +- _160 = _1; +- _158 = Add(move _159, move _160); +- StorageDead(_160); ++ _158 = Add(move _159, _1); + StorageDead(_159); + _157 = opaque::(move _158) -> [return: bb37, unwind unreachable]; + } + + bb37: { + StorageDead(_158); + StorageDead(_157); + StorageLive(_161); + StorageLive(_162); + StorageLive(_163); + _163 = (*_156); +- StorageLive(_164); +- _164 = _1; +- _162 = Add(move _163, move _164); +- StorageDead(_164); ++ _162 = Add(move _163, _1); + StorageDead(_163); + _161 = opaque::(move _162) -> [return: bb38, unwind unreachable]; + } + + bb38: { + StorageDead(_162); + StorageDead(_161); +- _146 = const (); + StorageDead(_156); + StorageDead(_147); +- StorageDead(_146); + StorageLive(_165); + _165 = &_3; + StorageLive(_166); +- StorageLive(_167); +- StorageLive(_168); + _168 = (*_165); +- StorageLive(_169); +- _169 = _1; +- _167 = Add(move _168, move _169); +- StorageDead(_169); +- StorageDead(_168); +- _166 = opaque::(move _167) -> [return: bb39, unwind unreachable]; ++ _167 = Add(_168, _1); ++ _166 = opaque::(_167) -> [return: bb39, unwind unreachable]; + } + + bb39: { +- StorageDead(_167); + StorageDead(_166); + StorageLive(_170); +- StorageLive(_171); +- StorageLive(_172); +- _172 = (*_165); +- StorageLive(_173); +- _173 = _1; +- _171 = Add(move _172, move _173); +- StorageDead(_173); +- StorageDead(_172); +- _170 = opaque::(move _171) -> [return: bb40, unwind unreachable]; ++ _170 = opaque::(_167) -> [return: bb40, unwind unreachable]; + } + + bb40: { +- StorageDead(_171); + StorageDead(_170); + _0 = const (); + StorageDead(_165); + StorageDead(_137); + StorageDead(_128); + return; + } + } + diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..68b052907192d --- /dev/null +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -0,0 +1,883 @@ +- // MIR for `subexpression_elimination` before GVN ++ // MIR for `subexpression_elimination` after GVN + + fn subexpression_elimination(_1: u64, _2: u64, _3: u64) -> () { + debug x => _1; + debug y => _2; + debug z => _3; + let mut _0: (); + let _4: (); + let mut _5: u64; + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let mut _11: u64; + let _12: (); + let mut _13: u64; + let mut _14: u64; + let mut _15: u64; + let _16: (); + let mut _17: u64; + let mut _18: u64; + let mut _19: u64; + let mut _20: bool; + let _21: (); + let mut _22: u64; + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: u64; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: u64; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: u64; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: u64; + let _46: (); + let mut _47: u32; + let mut _48: u64; + let _49: (); + let mut _50: f32; + let mut _51: u64; + let _52: (); + let mut _53: S; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: S; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u64; + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let mut _69: u64; + let mut _70: u64; + let _71: (); + let mut _72: u64; + let mut _73: u64; + let mut _74: u64; + let mut _75: u64; + let mut _76: u64; + let _77: (); + let mut _78: u64; + let mut _79: u64; + let mut _80: u64; + let mut _81: u64; + let mut _82: bool; + let mut _83: u64; + let _84: (); + let mut _85: u64; + let mut _86: u64; + let mut _87: u64; + let mut _88: u64; + let mut _89: bool; + let mut _90: u64; + let _91: (); + let mut _92: u64; + let mut _93: u64; + let mut _94: u64; + let mut _95: u64; + let mut _96: u64; + let _97: (); + let mut _98: u64; + let mut _99: u64; + let mut _100: u64; + let mut _101: u64; + let mut _102: u64; + let _103: (); + let mut _104: u64; + let mut _105: u64; + let mut _106: u64; + let mut _107: u64; + let mut _108: u64; + let _109: (); + let mut _110: u64; + let mut _111: u64; + let mut _112: u64; + let mut _113: u64; + let mut _114: u64; + let _115: (); + let mut _116: u64; + let mut _117: u64; + let mut _118: u64; + let mut _119: u64; + let mut _120: u64; + let _121: (); + let mut _122: S; + let mut _123: u64; + let _124: (); + let mut _125: u64; + let mut _126: S; + let mut _127: u64; + let _128: &u64; + let _129: (); + let mut _130: u64; + let mut _131: u64; + let mut _132: u64; + let _133: (); + let mut _134: u64; + let mut _135: u64; + let mut _136: u64; + let _138: (); + let mut _139: u64; + let mut _140: u64; + let mut _141: u64; + let _142: (); + let mut _143: u64; + let mut _144: u64; + let mut _145: u64; + let _146: (); + let _148: (); + let mut _149: u64; + let mut _150: u64; + let mut _151: u64; + let _152: (); + let mut _153: u64; + let mut _154: u64; + let mut _155: u64; + let _157: (); + let mut _158: u64; + let mut _159: u64; + let mut _160: u64; + let _161: (); + let mut _162: u64; + let mut _163: u64; + let mut _164: u64; + let _166: (); + let mut _167: u64; + let mut _168: u64; + let mut _169: u64; + let _170: (); + let mut _171: u64; + let mut _172: u64; + let mut _173: u64; + scope 1 { + debug a => _128; + let _137: &mut u64; + scope 2 { + debug b => _137; + let _165: &u64; + scope 3 { + let _147: *const u64; + scope 4 { + debug c => _147; + let _156: *mut u64; + scope 5 { + debug d => _156; + } + } + } + scope 6 { + debug e => _165; + } + } + } + + bb0: { + StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- StorageLive(_7); +- _7 = _2; +- _5 = Add(move _6, move _7); +- StorageDead(_7); +- StorageDead(_6); +- _4 = opaque::(move _5) -> [return: bb1, unwind continue]; ++ _5 = Add(_1, _2); ++ _4 = opaque::(_5) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_5); + StorageDead(_4); + StorageLive(_8); +- StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- StorageLive(_11); +- _11 = _2; +- _9 = Mul(move _10, move _11); +- StorageDead(_11); +- StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind continue]; ++ _9 = Mul(_1, _2); ++ _8 = opaque::(_9) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); +- StorageLive(_14); +- _14 = _1; +- StorageLive(_15); +- _15 = _2; +- _13 = Sub(move _14, move _15); +- StorageDead(_15); +- StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind continue]; ++ _13 = Sub(_1, _2); ++ _12 = opaque::(_13) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_16); +- StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- StorageLive(_19); +- _19 = _2; +- _20 = Eq(_19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind continue]; ++ _20 = Eq(_2, const 0_u64); ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind continue]; + } + + bb4: { +- _17 = Div(move _18, move _19); +- StorageDead(_19); +- StorageDead(_18); +- _16 = opaque::(move _17) -> [return: bb5, unwind continue]; ++ _17 = Div(_1, _2); ++ _16 = opaque::(_17) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_17); + StorageDead(_16); + StorageLive(_21); +- StorageLive(_22); +- StorageLive(_23); +- _23 = _1; +- StorageLive(_24); +- _24 = _2; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind continue]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind continue]; + } + + bb6: { +- _22 = Rem(move _23, move _24); +- StorageDead(_24); +- StorageDead(_23); +- _21 = opaque::(move _22) -> [return: bb7, unwind continue]; ++ _22 = Rem(_1, _2); ++ _21 = opaque::(_22) -> [return: bb7, unwind continue]; + } + + bb7: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_26); +- StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- StorageLive(_29); +- _29 = _2; +- _27 = BitAnd(move _28, move _29); +- StorageDead(_29); +- StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb8, unwind continue]; ++ _27 = BitAnd(_1, _2); ++ _26 = opaque::(_27) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_27); + StorageDead(_26); + StorageLive(_30); +- StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- StorageLive(_33); +- _33 = _2; +- _31 = BitOr(move _32, move _33); +- StorageDead(_33); +- StorageDead(_32); +- _30 = opaque::(move _31) -> [return: bb9, unwind continue]; ++ _31 = BitOr(_1, _2); ++ _30 = opaque::(_31) -> [return: bb9, unwind continue]; + } + + bb9: { +- StorageDead(_31); + StorageDead(_30); + StorageLive(_34); +- StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- StorageLive(_37); +- _37 = _2; +- _35 = BitXor(move _36, move _37); +- StorageDead(_37); +- StorageDead(_36); +- _34 = opaque::(move _35) -> [return: bb10, unwind continue]; ++ _35 = BitXor(_1, _2); ++ _34 = opaque::(_35) -> [return: bb10, unwind continue]; + } + + bb10: { +- StorageDead(_35); + StorageDead(_34); + StorageLive(_38); +- StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- StorageLive(_41); +- _41 = _2; +- _39 = Shl(move _40, move _41); +- StorageDead(_41); +- StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb11, unwind continue]; ++ _39 = Shl(_1, _2); ++ _38 = opaque::(_39) -> [return: bb11, unwind continue]; + } + + bb11: { +- StorageDead(_39); + StorageDead(_38); + StorageLive(_42); +- StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- StorageLive(_45); +- _45 = _2; +- _43 = Shr(move _44, move _45); +- StorageDead(_45); +- StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb12, unwind continue]; ++ _43 = Shr(_1, _2); ++ _42 = opaque::(_43) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = move _48 as u32 (IntToInt); +- StorageDead(_48); ++ _47 = _1 as u32 (IntToInt); + _46 = opaque::(move _47) -> [return: bb13, unwind continue]; + } + + bb13: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = move _51 as f32 (IntToFloat); +- StorageDead(_51); ++ _50 = _1 as f32 (IntToFloat); + _49 = opaque::(move _50) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); +- StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = S::(move _54); +- StorageDead(_54); +- _52 = opaque::>(move _53) -> [return: bb15, unwind continue]; ++ _53 = S::(_1); ++ _52 = opaque::>(_53) -> [return: bb15, unwind continue]; + } + + bb15: { +- StorageDead(_53); + StorageDead(_52); + StorageLive(_55); +- StorageLive(_56); +- StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = S::(move _58); +- StorageDead(_58); +- _56 = (_57.0: u64); +- _55 = opaque::(move _56) -> [return: bb16, unwind continue]; ++ _56 = (_53.0: u64); ++ _55 = opaque::(_56) -> [return: bb16, unwind continue]; + } + + bb16: { +- StorageDead(_56); +- StorageDead(_57); + StorageDead(_55); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- StorageLive(_62); +- _62 = _1; +- StorageLive(_63); +- _63 = _2; +- _61 = Add(move _62, move _63); +- StorageDead(_63); +- StorageDead(_62); + StorageLive(_64); + _64 = _3; +- _60 = Add(move _61, move _64); ++ _60 = Add(_5, move _64); + StorageDead(_64); +- StorageDead(_61); + _59 = opaque::(move _60) -> [return: bb17, unwind continue]; + } + + bb17: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- StorageLive(_68); +- _68 = _1; +- StorageLive(_69); +- _69 = _2; +- _67 = Mul(move _68, move _69); +- StorageDead(_69); +- StorageDead(_68); + StorageLive(_70); + _70 = _3; +- _66 = Add(move _67, move _70); ++ _66 = Add(_9, move _70); + StorageDead(_70); +- StorageDead(_67); + _65 = opaque::(move _66) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- StorageLive(_74); +- _74 = _1; +- StorageLive(_75); +- _75 = _2; +- _73 = Sub(move _74, move _75); +- StorageDead(_75); +- StorageDead(_74); + StorageLive(_76); + _76 = _3; +- _72 = Add(move _73, move _76); ++ _72 = Add(_13, move _76); + StorageDead(_76); +- StorageDead(_73); + _71 = opaque::(move _72) -> [return: bb19, unwind continue]; + } + + bb19: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- StorageLive(_80); +- _80 = _1; +- StorageLive(_81); +- _81 = _2; +- _82 = Eq(_81, const 0_u64); +- assert(!move _82, "attempt to divide `{}` by zero", _80) -> [success: bb20, unwind continue]; ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind continue]; + } + + bb20: { +- _79 = Div(move _80, move _81); +- StorageDead(_81); +- StorageDead(_80); + StorageLive(_83); + _83 = _3; +- _78 = Add(move _79, move _83); ++ _78 = Add(_17, move _83); + StorageDead(_83); +- StorageDead(_79); + _77 = opaque::(move _78) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_84); + StorageLive(_85); +- StorageLive(_86); +- StorageLive(_87); +- _87 = _1; +- StorageLive(_88); +- _88 = _2; +- _89 = Eq(_88, const 0_u64); +- assert(!move _89, "attempt to calculate the remainder of `{}` with a divisor of zero", _87) -> [success: bb22, unwind continue]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind continue]; + } + + bb22: { +- _86 = Rem(move _87, move _88); +- StorageDead(_88); +- StorageDead(_87); + StorageLive(_90); + _90 = _3; +- _85 = Add(move _86, move _90); ++ _85 = Add(_22, move _90); + StorageDead(_90); +- StorageDead(_86); + _84 = opaque::(move _85) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_85); + StorageDead(_84); + StorageLive(_91); + StorageLive(_92); +- StorageLive(_93); +- StorageLive(_94); +- _94 = _1; +- StorageLive(_95); +- _95 = _2; +- _93 = BitAnd(move _94, move _95); +- StorageDead(_95); +- StorageDead(_94); + StorageLive(_96); + _96 = _3; +- _92 = Add(move _93, move _96); ++ _92 = Add(_27, move _96); + StorageDead(_96); +- StorageDead(_93); + _91 = opaque::(move _92) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_92); + StorageDead(_91); + StorageLive(_97); + StorageLive(_98); +- StorageLive(_99); +- StorageLive(_100); +- _100 = _1; +- StorageLive(_101); +- _101 = _2; +- _99 = BitOr(move _100, move _101); +- StorageDead(_101); +- StorageDead(_100); + StorageLive(_102); + _102 = _3; +- _98 = Add(move _99, move _102); ++ _98 = Add(_31, move _102); + StorageDead(_102); +- StorageDead(_99); + _97 = opaque::(move _98) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_98); + StorageDead(_97); + StorageLive(_103); + StorageLive(_104); +- StorageLive(_105); +- StorageLive(_106); +- _106 = _1; +- StorageLive(_107); +- _107 = _2; +- _105 = BitXor(move _106, move _107); +- StorageDead(_107); +- StorageDead(_106); + StorageLive(_108); + _108 = _3; +- _104 = Add(move _105, move _108); ++ _104 = Add(_35, move _108); + StorageDead(_108); +- StorageDead(_105); + _103 = opaque::(move _104) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_104); + StorageDead(_103); + StorageLive(_109); + StorageLive(_110); +- StorageLive(_111); +- StorageLive(_112); +- _112 = _1; +- StorageLive(_113); +- _113 = _2; +- _111 = Shl(move _112, move _113); +- StorageDead(_113); +- StorageDead(_112); + StorageLive(_114); + _114 = _3; +- _110 = Add(move _111, move _114); ++ _110 = Add(_39, move _114); + StorageDead(_114); +- StorageDead(_111); + _109 = opaque::(move _110) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_110); + StorageDead(_109); + StorageLive(_115); + StorageLive(_116); +- StorageLive(_117); +- StorageLive(_118); +- _118 = _1; +- StorageLive(_119); +- _119 = _2; +- _117 = Shr(move _118, move _119); +- StorageDead(_119); +- StorageDead(_118); + StorageLive(_120); + _120 = _3; +- _116 = Add(move _117, move _120); ++ _116 = Add(_43, move _120); + StorageDead(_120); +- StorageDead(_117); + _115 = opaque::(move _116) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_116); + StorageDead(_115); + StorageLive(_121); +- StorageLive(_122); +- StorageLive(_123); +- _123 = _1; +- _122 = S::(move _123); +- StorageDead(_123); +- _121 = opaque::>(move _122) -> [return: bb29, unwind continue]; ++ _121 = opaque::>(_53) -> [return: bb29, unwind continue]; + } + + bb29: { +- StorageDead(_122); + StorageDead(_121); + StorageLive(_124); +- StorageLive(_125); +- StorageLive(_126); +- StorageLive(_127); +- _127 = _1; +- _126 = S::(move _127); +- StorageDead(_127); +- _125 = (_126.0: u64); +- _124 = opaque::(move _125) -> [return: bb30, unwind continue]; ++ _124 = opaque::(_56) -> [return: bb30, unwind continue]; + } + + bb30: { +- StorageDead(_125); +- StorageDead(_126); + StorageDead(_124); + StorageLive(_128); + _128 = &_3; + StorageLive(_129); +- StorageLive(_130); +- StorageLive(_131); + _131 = (*_128); +- StorageLive(_132); +- _132 = _1; +- _130 = Add(move _131, move _132); +- StorageDead(_132); +- StorageDead(_131); +- _129 = opaque::(move _130) -> [return: bb31, unwind continue]; ++ _130 = Add(_131, _1); ++ _129 = opaque::(_130) -> [return: bb31, unwind continue]; + } + + bb31: { +- StorageDead(_130); + StorageDead(_129); + StorageLive(_133); +- StorageLive(_134); +- StorageLive(_135); +- _135 = (*_128); +- StorageLive(_136); +- _136 = _1; +- _134 = Add(move _135, move _136); +- StorageDead(_136); +- StorageDead(_135); +- _133 = opaque::(move _134) -> [return: bb32, unwind continue]; ++ _133 = opaque::(_130) -> [return: bb32, unwind continue]; + } + + bb32: { +- StorageDead(_134); + StorageDead(_133); + StorageLive(_137); + _137 = &mut _3; + StorageLive(_138); + StorageLive(_139); + StorageLive(_140); + _140 = (*_137); +- StorageLive(_141); +- _141 = _1; +- _139 = Add(move _140, move _141); +- StorageDead(_141); ++ _139 = Add(move _140, _1); + StorageDead(_140); + _138 = opaque::(move _139) -> [return: bb33, unwind continue]; + } + + bb33: { + StorageDead(_139); + StorageDead(_138); + StorageLive(_142); + StorageLive(_143); + StorageLive(_144); + _144 = (*_137); +- StorageLive(_145); +- _145 = _1; +- _143 = Add(move _144, move _145); +- StorageDead(_145); ++ _143 = Add(move _144, _1); + StorageDead(_144); + _142 = opaque::(move _143) -> [return: bb34, unwind continue]; + } + + bb34: { + StorageDead(_143); + StorageDead(_142); +- StorageLive(_146); + StorageLive(_147); + _147 = &raw const _3; + StorageLive(_148); + StorageLive(_149); + StorageLive(_150); + _150 = (*_147); +- StorageLive(_151); +- _151 = _1; +- _149 = Add(move _150, move _151); +- StorageDead(_151); ++ _149 = Add(move _150, _1); + StorageDead(_150); + _148 = opaque::(move _149) -> [return: bb35, unwind continue]; + } + + bb35: { + StorageDead(_149); + StorageDead(_148); + StorageLive(_152); + StorageLive(_153); + StorageLive(_154); + _154 = (*_147); +- StorageLive(_155); +- _155 = _1; +- _153 = Add(move _154, move _155); +- StorageDead(_155); ++ _153 = Add(move _154, _1); + StorageDead(_154); + _152 = opaque::(move _153) -> [return: bb36, unwind continue]; + } + + bb36: { + StorageDead(_153); + StorageDead(_152); + StorageLive(_156); + _156 = &raw mut _3; + StorageLive(_157); + StorageLive(_158); + StorageLive(_159); + _159 = (*_156); +- StorageLive(_160); +- _160 = _1; +- _158 = Add(move _159, move _160); +- StorageDead(_160); ++ _158 = Add(move _159, _1); + StorageDead(_159); + _157 = opaque::(move _158) -> [return: bb37, unwind continue]; + } + + bb37: { + StorageDead(_158); + StorageDead(_157); + StorageLive(_161); + StorageLive(_162); + StorageLive(_163); + _163 = (*_156); +- StorageLive(_164); +- _164 = _1; +- _162 = Add(move _163, move _164); +- StorageDead(_164); ++ _162 = Add(move _163, _1); + StorageDead(_163); + _161 = opaque::(move _162) -> [return: bb38, unwind continue]; + } + + bb38: { + StorageDead(_162); + StorageDead(_161); +- _146 = const (); + StorageDead(_156); + StorageDead(_147); +- StorageDead(_146); + StorageLive(_165); + _165 = &_3; + StorageLive(_166); +- StorageLive(_167); +- StorageLive(_168); + _168 = (*_165); +- StorageLive(_169); +- _169 = _1; +- _167 = Add(move _168, move _169); +- StorageDead(_169); +- StorageDead(_168); +- _166 = opaque::(move _167) -> [return: bb39, unwind continue]; ++ _167 = Add(_168, _1); ++ _166 = opaque::(_167) -> [return: bb39, unwind continue]; + } + + bb39: { +- StorageDead(_167); + StorageDead(_166); + StorageLive(_170); +- StorageLive(_171); +- StorageLive(_172); +- _172 = (*_165); +- StorageLive(_173); +- _173 = _1; +- _171 = Add(move _172, move _173); +- StorageDead(_173); +- StorageDead(_172); +- _170 = opaque::(move _171) -> [return: bb40, unwind continue]; ++ _170 = opaque::(_167) -> [return: bb40, unwind continue]; + } + + bb40: { +- StorageDead(_171); + StorageDead(_170); + _0 = const (); + StorageDead(_165); + StorageDead(_137); + StorageDead(_128); + return; + } + } + diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff new file mode 100644 index 0000000000000..f33845502ad94 --- /dev/null +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff @@ -0,0 +1,45 @@ +- // MIR for `wrap_unwrap` before GVN ++ // MIR for `wrap_unwrap` after GVN + + fn wrap_unwrap(_1: T) -> T { + debug x => _1; + let mut _0: T; + let mut _2: std::option::Option; + let mut _3: T; + let mut _4: isize; + let _5: T; + let mut _6: !; + scope 1 { + debug y => _5; + } + + bb0: { + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = Option::::Some(move _3); +- StorageDead(_3); ++ _2 = Option::::Some(_1); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + StorageLive(_6); + _6 = begin_panic::<&str>(const "explicit panic") -> unwind unreachable; + } + + bb2: { + unreachable; + } + + bb3: { +- StorageLive(_5); + _5 = ((_2 as Some).0: T); + _0 = _5; +- StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..edc05f99fe2f7 --- /dev/null +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff @@ -0,0 +1,45 @@ +- // MIR for `wrap_unwrap` before GVN ++ // MIR for `wrap_unwrap` after GVN + + fn wrap_unwrap(_1: T) -> T { + debug x => _1; + let mut _0: T; + let mut _2: std::option::Option; + let mut _3: T; + let mut _4: isize; + let _5: T; + let mut _6: !; + scope 1 { + debug y => _5; + } + + bb0: { + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = Option::::Some(move _3); +- StorageDead(_3); ++ _2 = Option::::Some(_1); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + StorageLive(_6); + _6 = begin_panic::<&str>(const "explicit panic") -> unwind continue; + } + + bb2: { + unreachable; + } + + bb3: { +- StorageLive(_5); + _5 = ((_2 as Some).0: T); + _0 = _5; +- StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir index 9384064c53e95..8a60f4b1bdc6f 100644 --- a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -4,8 +4,8 @@ fn foo(_1: T, _2: i32) -> i32 { debug _t => _1; debug q => _2; let mut _0: i32; - let _3: [closure@foo::{closure#0}]; - let mut _4: &[closure@foo::{closure#0}]; + let _3: {closure@foo::{closure#0}}; + let mut _4: &{closure@foo::{closure#0}}; let mut _5: (i32, i32); let mut _6: i32; let mut _7: i32; @@ -21,7 +21,7 @@ fn foo(_1: T, _2: i32) -> i32 { bb0: { StorageLive(_3); - _3 = [closure@foo::::{closure#0}]; + _3 = {closure@foo::::{closure#0}}; StorageLive(_4); _4 = &_3; StorageLive(_5); diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index 17676638a7709..6e77a9bc575c1 100644 --- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -4,8 +4,8 @@ fn foo(_1: T, _2: &i32) -> i32 { debug _t => _1; debug q => _2; let mut _0: i32; - let _3: [closure@foo::{closure#0}]; - let mut _4: &[closure@foo::{closure#0}]; + let _3: {closure@foo::{closure#0}}; + let mut _4: &{closure@foo::{closure#0}}; let mut _5: (&i32, &i32); let mut _6: &i32; let mut _7: &i32; @@ -24,7 +24,7 @@ fn foo(_1: T, _2: &i32) -> i32 { bb0: { StorageLive(_3); - _3 = [closure@foo::::{closure#0}]; + _3 = {closure@foo::::{closure#0}}; StorageLive(_4); _4 = &_3; StorageLive(_5); diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index b8178d201261f..10b81e59b5f4b 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -4,10 +4,10 @@ fn foo(_1: T, _2: i32) -> (i32, T) { debug t => _1; debug q => _2; let mut _0: (i32, T); - let _3: [closure@foo::{closure#0}]; + let _3: {closure@foo::{closure#0}}; let mut _4: &i32; let mut _5: &T; - let mut _6: &[closure@foo::{closure#0}]; + let mut _6: &{closure@foo::{closure#0}}; let mut _7: (i32,); let mut _8: i32; let mut _9: i32; @@ -30,7 +30,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _4 = &_2; StorageLive(_5); _5 = &_1; - _3 = [closure@foo::::{closure#0}] { q: move _4, t: move _5 }; + _3 = {closure@foo::::{closure#0}} { q: move _4, t: move _5 }; StorageDead(_5); StorageDead(_4); StorageLive(_6); @@ -41,15 +41,19 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _7 = (move _8,); StorageLive(_9); _9 = move (_7.0: i32); + StorageLive(_10); + StorageLive(_12); StorageLive(_11); - _10 = deref_copy ((*_6).0: &i32); + _10 = ((*_6).0: &i32); _11 = (*_10); StorageLive(_13); - _12 = deref_copy ((*_6).1: &T); + _12 = ((*_6).1: &T); _13 = (*_12); _0 = (move _11, move _13); StorageDead(_13); StorageDead(_11); + StorageDead(_12); + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index e05c605a4e47f..06ee8c464d5ba 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -4,30 +4,28 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; - let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>; + let mut _3: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _4: {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { ++ scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -36,71 +34,78 @@ StorageLive(_3); StorageLive(_4); - _4 = g() -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; - _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind unreachable]; -- } -- -- bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; - StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; ++ _4 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; ++ _3 = &mut _4; ++ _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}> { pointer: move _3 }; ++ StorageDead(_3); + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); ++ StorageLive(_6); ++ StorageLive(_7); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb2, 1: bb6, 3: bb7, otherwise: bb8]; ++ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } -- bb3: { -+ bb1: { + bb1: { +- _3 = &mut _4; +- _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind unreachable]; ++ StorageDead(_7); ++ StorageDead(_6); + StorageDead(_5); - StorageDead(_2); - StorageDead(_4); - _0 = const (); - StorageDead(_1); - return; -+ } -+ -+ bb2: { ++ StorageDead(_2); ++ drop(_4) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_3); +- _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; ++ StorageDead(_4); ++ _0 = const (); ++ StorageDead(_1); ++ return; + } + + bb3: { +- StorageDead(_2); +- drop(_4) -> [return: bb4, unwind unreachable]; + StorageLive(_8); -+ switchInt(_5) -> [0: bb3, otherwise: bb4]; -+ } -+ -+ bb3: { ++ switchInt(_5) -> [0: bb4, otherwise: bb5]; + } + + bb4: { +- StorageDead(_4); +- _0 = const (); +- StorageDead(_1); +- return; + _8 = const 13_i32; -+ goto -> bb5; ++ goto -> bb6; + } + -+ bb4: { ++ bb5: { + _8 = const 7_i32; -+ goto -> bb5; ++ goto -> bb6; + } + -+ bb5: { ++ bb6: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); -+ discriminant((*_9)) = 3; ++ discriminant((*_6)) = 3; + goto -> bb1; + } + -+ bb6: { -+ assert(const false, "generator resumed after completion") -> [success: bb6, unwind unreachable]; ++ bb7: { ++ assert(const false, "generator resumed after completion") -> [success: bb7, unwind unreachable]; + } + -+ bb7: { ++ bb8: { + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); -+ discriminant((*_10)) = 1; ++ discriminant((*_6)) = 1; + goto -> bb1; + } + -+ bb8: { ++ bb9: { + unreachable; } } diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index fedcf04231d7b..da29ba5f50d73 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -4,30 +4,28 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; - let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>; + let mut _3: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _4: {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { ++ scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -39,73 +37,87 @@ - } - - bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; ++ _4 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind: bb4]; +- _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind: bb5]; - } - - bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; ++ _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}> { pointer: move _3 }; StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; +- _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); ++ StorageLive(_6); ++ StorageLive(_7); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; ++ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } - bb3: { + bb1: { ++ StorageDead(_7); ++ StorageDead(_6); + StorageDead(_5); StorageDead(_2); +- drop(_4) -> [return: bb4, unwind: bb6]; ++ drop(_4) -> [return: bb2, unwind: bb4]; + } + +- bb4: { ++ bb2: { StorageDead(_4); _0 = const (); StorageDead(_1); return; } -- bb4 (cleanup): { -+ bb2 (cleanup): { +- bb5 (cleanup): { +- drop(_4) -> [return: bb6, unwind terminate(cleanup)]; ++ bb3 (cleanup): { ++ drop(_4) -> [return: bb4, unwind terminate(cleanup)]; + } + +- bb6 (cleanup): { ++ bb4 (cleanup): { resume; + } + -+ bb3: { ++ bb5: { + StorageLive(_8); -+ switchInt(_5) -> [0: bb4, otherwise: bb5]; ++ switchInt(_5) -> [0: bb6, otherwise: bb7]; + } + -+ bb4: { ++ bb6: { + _8 = const 13_i32; -+ goto -> bb6; ++ goto -> bb8; + } + -+ bb5: { ++ bb7: { + _8 = const 7_i32; -+ goto -> bb6; ++ goto -> bb8; + } + -+ bb6: { ++ bb8: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); -+ discriminant((*_9)) = 3; ++ discriminant((*_6)) = 3; + goto -> bb1; + } + -+ bb7: { -+ assert(const false, "generator resumed after completion") -> [success: bb7, unwind: bb2]; ++ bb9: { ++ assert(const false, "generator resumed after completion") -> [success: bb9, unwind: bb3]; + } + -+ bb8: { ++ bb10: { + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); -+ discriminant((*_10)) = 1; ++ discriminant((*_6)) = 1; + goto -> bb1; + } + -+ bb9: { ++ bb11: { + unreachable; } } 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 dc0ab255afd9d..b90e0505c54e2 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 @@ -122,9 +122,14 @@ + _3 = const _; + _2 = Vec:: { buf: move _3, len: const 0_usize }; + StorageDead(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); + StorageLive(_8); ++ StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); @@ -178,10 +183,15 @@ + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); ++ StorageDead(_10); + StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; 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 675292f06d669..f9c637caa18a8 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 @@ -122,9 +122,14 @@ + _3 = const _; + _2 = Vec:: { buf: move _3, len: const 0_usize }; + StorageDead(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); + StorageLive(_8); ++ StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); @@ -195,10 +200,15 @@ + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); ++ StorageDead(_10); + StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff index 3d0c10725275d..688ab9c563a7a 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff @@ -18,6 +18,7 @@ bb0: { - _0 = inner() -> [return: bb1, unwind unreachable]; + StorageLive(_1); ++ StorageLive(_2); + _1 = const _; + _0 = index() -> [return: bb1, unwind unreachable]; } @@ -40,6 +41,7 @@ + + bb4: { + StorageDead(_3); ++ StorageDead(_2); + StorageDead(_1); return; } diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff index 16a19f4a3569a..e4d2b1a7ffbdd 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff @@ -18,6 +18,7 @@ bb0: { - _0 = inner() -> [return: bb1, unwind continue]; + StorageLive(_1); ++ StorageLive(_2); + _1 = const _; + _0 = index() -> [return: bb1, unwind continue]; } @@ -40,6 +41,7 @@ + + bb4: { + StorageDead(_3); ++ StorageDead(_2); + StorageDead(_1); return; } diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 6837da27a96f9..62d7e839f5a84 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -17,9 +17,13 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_3); StorageLive(_4); _4 = &mut (*_1); + StorageLive(_5); + StorageLive(_6); _5 = deref_copy (*_4); _6 = (((_5.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); _3 = &mut (*_6); + StorageDead(_6); + StorageDead(_5); _2 = &mut (*_3); StorageDead(_4); _0 = &mut (*_2); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index d09bfc33ff13a..bc0aa06a7523c 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -15,9 +15,13 @@ fn d(_1: &Box) -> &T { StorageLive(_2); StorageLive(_3); _3 = &(*_1); + StorageLive(_4); + StorageLive(_5); _4 = deref_copy (*_3); _5 = (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); _2 = &(*_5); + StorageDead(_5); + StorageDead(_4); _0 = &(*_2); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index ef91f50403348..4d170c41f9719 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -2,8 +2,8 @@ fn main() -> () { let mut _0: (); - let _1: [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; - let mut _2: &[closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; + let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16}; + let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16}; let mut _3: ((),); let mut _4: (); let mut _5: (); @@ -19,7 +19,7 @@ fn main() -> () { bb0: { StorageLive(_1); - _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; + _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16}; StorageLive(_2); _2 = &_1; StorageLive(_3); diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff index c94dd2556956c..b532b133a83a5 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff @@ -15,28 +15,44 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind unreachable]; + _4 = hide_foo() -> [return: bb1, unwind: bb6]; } bb1: { _3 = &_4; StorageLive(_5); _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; } bb2: { StorageDead(_5); StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; + drop(_1) -> [return: bb4, unwind: bb7]; } - bb3: { + bb4: { return; } + + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + resume; + } } diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff index cbfb39115b370..bcebcf297c2b1 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff @@ -15,35 +15,43 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb4]; + _4 = hide_foo() -> [return: bb1, unwind: bb6]; } bb1: { _3 = &_4; StorageLive(_5); _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; } bb2: { StorageDead(_5); StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind: bb5]; + drop(_1) -> [return: bb4, unwind continue]; } - bb3: { + bb4: { return; } - bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate(cleanup)]; + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; } - bb5 (cleanup): { + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { resume; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index e3c57347392a5..018b6c1ee958c 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -30,6 +30,7 @@ _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; + StorageLive(_3); ++ StorageLive(_4); + _4 = discriminant(_2); + switchInt(move _4) -> [1: bb2, otherwise: bb1]; } @@ -40,6 +41,7 @@ + + bb2: { + _0 = move ((_2 as Some).0: T); ++ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index fc638cb3acef4..47845758a3f61 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -30,6 +30,7 @@ _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; + StorageLive(_3); ++ StorageLive(_4); + _4 = discriminant(_2); + switchInt(move _4) -> [1: bb2, otherwise: bb1]; } @@ -44,6 +45,7 @@ - resume; + bb2: { + _0 = move ((_2 as Some).0: T); ++ StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index fcc4d43ced66e..392f085bd4d1d 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option) -> T { bb0: { StorageLive(_3); + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [1: bb1, otherwise: bb2]; } bb1: { _0 = move ((_1 as Some).0: T); + StorageDead(_2); StorageDead(_3); return; } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index fcc4d43ced66e..392f085bd4d1d 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option) -> T { bb0: { StorageLive(_3); + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [1: bb1, otherwise: bb2]; } bb1: { _0 = move ((_1 as Some).0: T); + StorageDead(_2); StorageDead(_3); return; } diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff index afcfde09c02f1..28a7ffda3717a 100644 --- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,7 +5,7 @@ let mut _0: bool; bb0: { -+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:20:1 - 22:2; ++ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:20:1 - 22:2]; _0 = const true; return; } diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index e17c6ddc56e55..9a8caa26307a1 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -8,12 +8,12 @@ let mut _3: !; bb0: { -+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:11:1 - 11:11; ++ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:11:1 - 11:11]; goto -> bb1; } bb1: { -+ Coverage::Expression(0) = Counter(0) + Counter(1) for /the/src/instrument_coverage.rs:12:5 - 13:17; ++ Coverage::Expression(0) = Counter(0) + Counter(1) for [/the/src/instrument_coverage.rs:12:5 - 13:17]; falseUnwind -> [real: bb2, unwind: bb6]; } @@ -27,15 +27,14 @@ } bb4: { -+ Coverage::Expression(2) = Expression(1) + Zero for /the/src/instrument_coverage.rs:17:1 - 17:2; -+ Coverage::Expression(1) = Expression(0) - Counter(1) for /the/src/instrument_coverage.rs:14:13 - 14:18; ++ Coverage::Expression(1) = Expression(0) - Counter(1) for [/the/src/instrument_coverage.rs:14:13 - 14:18, /the/src/instrument_coverage.rs:17:1 - 17:2]; _0 = const (); StorageDead(_2); return; } bb5: { -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:15:10 - 15:11; ++ Coverage::Counter(1) for [/the/src/instrument_coverage.rs:15:10 - 15:11]; _1 = const (); StorageDead(_2); goto -> bb1; diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff b/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff index ce490e894f038..3748d14838032 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff @@ -33,6 +33,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + _4 = const 0_u32; StorageLive(_15); StorageLive(_14); _14 = Shr(_1, const 0_i32); diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff index 254557b9947f1..9dab4233c5681 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff @@ -33,6 +33,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + _4 = const 0_u32; StorageLive(_15); StorageLive(_14); _14 = Shr(_1, const 0_i32); diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index f8c85941813cc..5d25c6557002c 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -3,56 +3,61 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; let mut _0: u32; - let mut _4: std::option::Option; + let mut _5: std::option::Option; scope 1 (inlined char::methods::::is_digit) { debug self => _1; debug radix => const 8_u32; let _2: std::option::Option; - let mut _7: &std::option::Option; + let mut _3: &std::option::Option; scope 2 (inlined Option::::is_some) { - debug self => _7; - let mut _3: isize; + debug self => _3; + let mut _4: isize; } } scope 3 (inlined #[track_caller] Option::::unwrap) { - debug self => _4; - let mut _5: isize; - let mut _6: !; + debug self => _5; + let mut _6: isize; + let mut _7: !; scope 4 { debug val => _0; } } bb0: { - StorageLive(_7); + StorageLive(_3); StorageLive(_2); _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = discriminant(_2); - StorageDead(_7); + _3 = &_2; + StorageLive(_4); + _4 = discriminant(_2); + StorageDead(_3); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, otherwise: bb7]; } bb2: { - StorageLive(_4); - _4 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; + StorageDead(_4); + StorageLive(_5); + _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; } bb3: { - _5 = discriminant(_4); - switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; + StorageLive(_6); + _6 = discriminant(_5); + switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; } bb4: { - _6 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; } bb5: { - _0 = move ((_4 as Some).0: u32); - StorageDead(_4); + _0 = move ((_5 as Some).0: u32); + StorageDead(_6); + StorageDead(_5); goto -> bb8; } @@ -61,6 +66,7 @@ fn num_to_digit(_1: char) -> u32 { } bb7: { + StorageDead(_4); _0 = const 0_u32; goto -> bb8; } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index df7392edc50c2..4677c0108e3bb 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -3,56 +3,61 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; let mut _0: u32; - let mut _4: std::option::Option; + let mut _5: std::option::Option; scope 1 (inlined char::methods::::is_digit) { debug self => _1; debug radix => const 8_u32; let _2: std::option::Option; - let mut _7: &std::option::Option; + let mut _3: &std::option::Option; scope 2 (inlined Option::::is_some) { - debug self => _7; - let mut _3: isize; + debug self => _3; + let mut _4: isize; } } scope 3 (inlined #[track_caller] Option::::unwrap) { - debug self => _4; - let mut _5: isize; - let mut _6: !; + debug self => _5; + let mut _6: isize; + let mut _7: !; scope 4 { debug val => _0; } } bb0: { - StorageLive(_7); + StorageLive(_3); StorageLive(_2); _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue]; } bb1: { - _3 = discriminant(_2); - StorageDead(_7); + _3 = &_2; + StorageLive(_4); + _4 = discriminant(_2); + StorageDead(_3); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, otherwise: bb7]; } bb2: { - StorageLive(_4); - _4 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; + StorageDead(_4); + StorageLive(_5); + _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; } bb3: { - _5 = discriminant(_4); - switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; + StorageLive(_6); + _6 = discriminant(_5); + switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; } bb4: { - _6 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; } bb5: { - _0 = move ((_4 as Some).0: u32); - StorageDead(_4); + _0 = move ((_5 as Some).0: u32); + StorageDead(_6); + StorageDead(_5); goto -> bb8; } @@ -61,6 +66,7 @@ fn num_to_digit(_1: char) -> u32 { } bb7: { + StorageDead(_4); _0 = const 0_u32; goto -> bb8; } diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir index 75f81c5aacaf2..cf7feef00514a 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir @@ -8,59 +8,62 @@ fn step_forward(_1: u32, _2: usize) -> u32 { debug start => _1; debug n => _2; let _3: std::option::Option; - let mut _6: bool; - let mut _7: u32; - let mut _8: &std::option::Option; + let mut _4: &std::option::Option; + let mut _7: bool; + let mut _8: u32; scope 2 { } scope 3 (inlined Option::::is_none) { - debug self => _8; - let mut _5: bool; + debug self => _4; + let mut _6: bool; scope 4 (inlined Option::::is_some) { - debug self => _8; - let mut _4: isize; + debug self => _4; + let mut _5: isize; } } scope 5 (inlined core::num::::wrapping_add) { debug self => _1; - debug rhs => _7; + debug rhs => _8; } } bb0: { - StorageLive(_6); - StorageLive(_8); + StorageLive(_7); + StorageLive(_4); StorageLive(_3); _3 = ::forward_checked(_1, _2) -> [return: bb1, unwind continue]; } bb1: { + _4 = &_3; + StorageLive(_6); StorageLive(_5); - _4 = discriminant(_3); - _5 = Eq(_4, const 1_isize); - _6 = Not(move _5); + _5 = discriminant(_3); + _6 = Eq(_5, const 1_isize); StorageDead(_5); - switchInt(move _6) -> [0: bb2, otherwise: bb3]; + _7 = Not(move _6); + StorageDead(_6); + switchInt(move _7) -> [0: bb2, otherwise: bb3]; } bb2: { StorageDead(_3); - StorageDead(_8); + StorageDead(_4); goto -> bb4; } bb3: { StorageDead(_3); - StorageDead(_8); + StorageDead(_4); assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> [success: bb4, unwind continue]; } bb4: { - StorageDead(_6); - StorageLive(_7); - _7 = _2 as u32 (IntToInt); - _0 = Add(_1, _7); StorageDead(_7); + StorageLive(_8); + _8 = _2 as u32 (IntToInt); + _0 = Add(_1, _8); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 4db829a5ec349..2fbe508826831 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -7,20 +7,20 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () let mut _3: std::iter::FilterMap, impl Fn(T) -> Option>; let mut _4: std::iter::FilterMap, impl Fn(T) -> Option>; let mut _5: std::iter::FilterMap, impl Fn(T) -> Option>; - let mut _8: std::option::Option; - let mut _9: isize; - let _11: (); - let mut _12: &mut std::iter::FilterMap, impl Fn(T) -> Option>; + let mut _6: &mut std::iter::FilterMap, impl Fn(T) -> Option>; + let mut _9: std::option::Option; + let mut _10: isize; + let _12: (); scope 1 { debug iter => _5; - let _10: U; + let _11: U; scope 2 { - debug x => _10; + debug x => _11; } scope 4 (inlined , impl Fn(T) -> Option> as Iterator>::next) { - debug self => _12; - let mut _6: &mut impl Iterator; - let mut _7: &mut impl Fn(T) -> Option; + debug self => _6; + let mut _7: &mut impl Iterator; + let mut _8: &mut impl Fn(T) -> Option; } } scope 3 (inlined , impl Fn(T) -> Option> as IntoIterator>::into_iter) { @@ -42,23 +42,24 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb2: { - StorageLive(_8); - StorageLive(_6); - _6 = &mut (_5.0: impl Iterator); + StorageLive(_9); + _6 = &mut _5; StorageLive(_7); - _7 = &mut (_5.1: impl Fn(T) -> Option); - _8 = as Iterator>::find_map:: Option>(move _6, move _7) -> [return: bb3, unwind: bb9]; + _7 = &mut (_5.0: impl Iterator); + StorageLive(_8); + _8 = &mut (_5.1: impl Fn(T) -> Option); + _9 = as Iterator>::find_map:: Option>(move _7, move _8) -> [return: bb3, unwind: bb9]; } bb3: { + StorageDead(_8); StorageDead(_7); - StorageDead(_6); - _9 = discriminant(_8); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb8]; + _10 = discriminant(_9); + switchInt(move _10) -> [0: bb4, 1: bb6, otherwise: bb8]; } bb4: { - StorageDead(_8); + StorageDead(_9); drop(_5) -> [return: bb5, unwind continue]; } @@ -69,12 +70,12 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb6: { - _10 = move ((_8 as Some).0: U); - _11 = opaque::(move _10) -> [return: bb7, unwind: bb9]; + _11 = move ((_9 as Some).0: U); + _12 = opaque::(move _11) -> [return: bb7, unwind: bb9]; } bb7: { - StorageDead(_8); + StorageDead(_9); goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 0d79f2de10d7b..49f685cfacdcc 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -6,35 +6,35 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _0: (); let mut _3: std::ops::Range; let mut _4: std::ops::Range; - let mut _8: std::option::Option; - let mut _11: isize; - let _13: (); - let mut _14: &mut std::ops::Range; + let mut _5: &mut std::ops::Range; + let mut _11: std::option::Option; + let mut _14: isize; + let _16: (); scope 1 { debug iter => _4; - let _12: usize; + let _15: usize; scope 2 { - debug i => _12; + debug i => _15; } scope 4 (inlined iter::range::>::next) { - debug self => _14; + debug self => _5; scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _14; - let mut _7: bool; - let _9: usize; - let mut _10: usize; - let mut _15: &usize; - let mut _16: &usize; + debug self => _5; + let mut _6: &usize; + let mut _7: &usize; + let mut _10: bool; + let _12: usize; + let mut _13: usize; scope 6 { - debug old => _9; + debug old => _12; scope 7 { } } scope 8 (inlined cmp::impls::::lt) { - debug self => _15; - debug other => _16; - let mut _5: usize; - let mut _6: usize; + debug self => _6; + debug other => _7; + let mut _8: usize; + let mut _9: usize; } } } @@ -51,63 +51,66 @@ fn int_range(_1: usize, _2: usize) -> () { } bb1: { + StorageLive(_11); + _5 = &mut _4; + StorageLive(_12); + StorageLive(_10); + StorageLive(_6); + _6 = &(_4.0: usize); + StorageLive(_7); + _7 = &(_4.1: usize); StorageLive(_8); + _8 = (_4.0: usize); StorageLive(_9); - StorageLive(_7); - StorageLive(_15); - StorageLive(_16); - StorageLive(_5); - _5 = (_4.0: usize); - StorageLive(_6); - _6 = (_4.1: usize); - _7 = Lt(move _5, move _6); - StorageDead(_6); - StorageDead(_5); - switchInt(move _7) -> [0: bb2, otherwise: bb3]; + _9 = (_4.1: usize); + _10 = Lt(move _8, move _9); + StorageDead(_9); + StorageDead(_8); + switchInt(move _10) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_16); - StorageDead(_15); - _8 = Option::::None; + StorageDead(_7); + StorageDead(_6); + _11 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_16); - StorageDead(_15); - _9 = (_4.0: usize); - StorageLive(_10); - _10 = ::forward_unchecked(_9, const 1_usize) -> [return: bb4, unwind continue]; + StorageDead(_7); + StorageDead(_6); + _12 = (_4.0: usize); + StorageLive(_13); + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb4, unwind continue]; } bb4: { - (_4.0: usize) = move _10; - StorageDead(_10); - _8 = Option::::Some(_9); + (_4.0: usize) = move _13; + StorageDead(_13); + _11 = Option::::Some(_12); goto -> bb5; } bb5: { - StorageDead(_7); - StorageDead(_9); - _11 = discriminant(_8); - switchInt(move _11) -> [0: bb6, 1: bb7, otherwise: bb9]; + StorageDead(_10); + StorageDead(_12); + _14 = discriminant(_11); + switchInt(move _14) -> [0: bb6, 1: bb7, otherwise: bb9]; } bb6: { - StorageDead(_8); + StorageDead(_11); StorageDead(_4); return; } bb7: { - _12 = ((_8 as Some).0: usize); - _13 = opaque::(move _12) -> [return: bb8, unwind continue]; + _15 = ((_11 as Some).0: usize); + _16 = opaque::(move _15) -> [return: bb8, unwind continue]; } bb8: { - StorageDead(_8); + StorageDead(_11); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 9664ccfb094f7..91c3731f4923f 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -7,37 +7,37 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _0: (); let mut _4: std::ops::Range; let mut _5: std::ops::Range; - let mut _9: std::option::Option; - let mut _12: isize; - let mut _14: &impl Fn(u32); - let mut _15: (u32,); - let _16: (); - let mut _17: &mut std::ops::Range; + let mut _6: &mut std::ops::Range; + let mut _12: std::option::Option; + let mut _15: isize; + let mut _17: &impl Fn(u32); + let mut _18: (u32,); + let _19: (); scope 1 { debug iter => _5; - let _13: u32; + let _16: u32; scope 2 { - debug x => _13; + debug x => _16; } scope 4 (inlined iter::range::>::next) { - debug self => _17; + debug self => _6; scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _17; - let mut _8: bool; - let _10: u32; - let mut _11: u32; - let mut _18: &u32; - let mut _19: &u32; + debug self => _6; + let mut _7: &u32; + let mut _8: &u32; + let mut _11: bool; + let _13: u32; + let mut _14: u32; scope 6 { - debug old => _10; + debug old => _13; scope 7 { } } scope 8 (inlined cmp::impls::::lt) { - debug self => _18; - debug other => _19; - let mut _6: u32; - let mut _7: u32; + debug self => _7; + debug other => _8; + let mut _9: u32; + let mut _10: u32; } } } @@ -54,52 +54,55 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb1: { + StorageLive(_12); + _6 = &mut _5; + StorageLive(_13); + StorageLive(_11); + StorageLive(_7); + _7 = &(_5.0: u32); + StorageLive(_8); + _8 = &(_5.1: u32); StorageLive(_9); + _9 = (_5.0: u32); StorageLive(_10); - StorageLive(_8); - StorageLive(_18); - StorageLive(_19); - StorageLive(_6); - _6 = (_5.0: u32); - StorageLive(_7); - _7 = (_5.1: u32); - _8 = Lt(move _6, move _7); - StorageDead(_7); - StorageDead(_6); - switchInt(move _8) -> [0: bb2, otherwise: bb3]; + _10 = (_5.1: u32); + _11 = Lt(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + switchInt(move _11) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_19); - StorageDead(_18); - _9 = Option::::None; + StorageDead(_8); + StorageDead(_7); + _12 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_19); - StorageDead(_18); - _10 = (_5.0: u32); - StorageLive(_11); - _11 = ::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable]; + StorageDead(_8); + StorageDead(_7); + _13 = (_5.0: u32); + StorageLive(_14); + _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; } bb4: { - (_5.0: u32) = move _11; - StorageDead(_11); - _9 = Option::::Some(_10); + (_5.0: u32) = move _14; + StorageDead(_14); + _12 = Option::::Some(_13); goto -> bb5; } bb5: { - StorageDead(_8); - StorageDead(_10); - _12 = discriminant(_9); - switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_11); + StorageDead(_13); + _15 = discriminant(_12); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_9); + StorageDead(_12); StorageDead(_5); drop(_3) -> [return: bb7, unwind unreachable]; } @@ -109,18 +112,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8: { - _13 = ((_9 as Some).0: u32); - StorageLive(_14); - _14 = &_3; - StorageLive(_15); - _15 = (_13,); - _16 = >::call(move _14, move _15) -> [return: bb9, unwind unreachable]; + _16 = ((_12 as Some).0: u32); + StorageLive(_17); + _17 = &_3; + StorageLive(_18); + _18 = (_16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_15); - StorageDead(_14); - StorageDead(_9); + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index dc8b46b6c08e3..f76de02c9d1e4 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -7,37 +7,37 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _0: (); let mut _4: std::ops::Range; let mut _5: std::ops::Range; - let mut _9: std::option::Option; - let mut _12: isize; - let mut _14: &impl Fn(u32); - let mut _15: (u32,); - let _16: (); - let mut _17: &mut std::ops::Range; + let mut _6: &mut std::ops::Range; + let mut _12: std::option::Option; + let mut _15: isize; + let mut _17: &impl Fn(u32); + let mut _18: (u32,); + let _19: (); scope 1 { debug iter => _5; - let _13: u32; + let _16: u32; scope 2 { - debug x => _13; + debug x => _16; } scope 4 (inlined iter::range::>::next) { - debug self => _17; + debug self => _6; scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _17; - let mut _8: bool; - let _10: u32; - let mut _11: u32; - let mut _18: &u32; - let mut _19: &u32; + debug self => _6; + let mut _7: &u32; + let mut _8: &u32; + let mut _11: bool; + let _13: u32; + let mut _14: u32; scope 6 { - debug old => _10; + debug old => _13; scope 7 { } } scope 8 (inlined cmp::impls::::lt) { - debug self => _18; - debug other => _19; - let mut _6: u32; - let mut _7: u32; + debug self => _7; + debug other => _8; + let mut _9: u32; + let mut _10: u32; } } } @@ -54,52 +54,55 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb1: { + StorageLive(_12); + _6 = &mut _5; + StorageLive(_13); + StorageLive(_11); + StorageLive(_7); + _7 = &(_5.0: u32); + StorageLive(_8); + _8 = &(_5.1: u32); StorageLive(_9); + _9 = (_5.0: u32); StorageLive(_10); - StorageLive(_8); - StorageLive(_18); - StorageLive(_19); - StorageLive(_6); - _6 = (_5.0: u32); - StorageLive(_7); - _7 = (_5.1: u32); - _8 = Lt(move _6, move _7); - StorageDead(_7); - StorageDead(_6); - switchInt(move _8) -> [0: bb2, otherwise: bb3]; + _10 = (_5.1: u32); + _11 = Lt(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + switchInt(move _11) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_19); - StorageDead(_18); - _9 = Option::::None; + StorageDead(_8); + StorageDead(_7); + _12 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_19); - StorageDead(_18); - _10 = (_5.0: u32); - StorageLive(_11); - _11 = ::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb11]; + StorageDead(_8); + StorageDead(_7); + _13 = (_5.0: u32); + StorageLive(_14); + _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb11]; } bb4: { - (_5.0: u32) = move _11; - StorageDead(_11); - _9 = Option::::Some(_10); + (_5.0: u32) = move _14; + StorageDead(_14); + _12 = Option::::Some(_13); goto -> bb5; } bb5: { - StorageDead(_8); - StorageDead(_10); - _12 = discriminant(_9); - switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_11); + StorageDead(_13); + _15 = discriminant(_12); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_9); + StorageDead(_12); StorageDead(_5); drop(_3) -> [return: bb7, unwind continue]; } @@ -109,18 +112,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8: { - _13 = ((_9 as Some).0: u32); - StorageLive(_14); - _14 = &_3; - StorageLive(_15); - _15 = (_13,); - _16 = >::call(move _14, move _15) -> [return: bb9, unwind: bb11]; + _16 = ((_12 as Some).0: u32); + StorageLive(_17); + _17 = &_3; + StorageLive(_18); + _18 = (_16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_15); - StorageDead(_14); - StorageDead(_9); + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index fff713b5a795d..a7824f36d505d 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -7,65 +7,67 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { debug self => _1; scope 2 (inlined as iter::range::RangeIteratorImpl>::spec_next) { debug self => _1; - let mut _4: bool; - let _5: u32; - let mut _6: u32; - let mut _7: &u32; - let mut _8: &u32; + let mut _2: &u32; + let mut _3: &u32; + let mut _6: bool; + let _7: u32; + let mut _8: u32; scope 3 { - debug old => _5; + debug old => _7; scope 4 { } } scope 5 (inlined cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _2: u32; - let mut _3: u32; + debug self => _2; + debug other => _3; + let mut _4: u32; + let mut _5: u32; } } } bb0: { - StorageLive(_5); - StorageLive(_4); StorageLive(_7); - StorageLive(_8); + StorageLive(_6); StorageLive(_2); - _2 = ((*_1).0: u32); + _2 = &((*_1).0: u32); StorageLive(_3); - _3 = ((*_1).1: u32); - _4 = Lt(move _2, move _3); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _3 = &((*_1).1: u32); + StorageLive(_4); + _4 = ((*_1).0: u32); + StorageLive(_5); + _5 = ((*_1).1: u32); + _6 = Lt(move _4, move _5); + StorageDead(_5); + StorageDead(_4); + switchInt(move _6) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_8); - StorageDead(_7); + StorageDead(_3); + StorageDead(_2); _0 = Option::::None; goto -> bb4; } bb2: { - StorageDead(_8); - StorageDead(_7); - _5 = ((*_1).0: u32); - StorageLive(_6); - _6 = ::forward_unchecked(_5, const 1_usize) -> [return: bb3, unwind unreachable]; + StorageDead(_3); + StorageDead(_2); + _7 = ((*_1).0: u32); + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb3, unwind unreachable]; } bb3: { - ((*_1).0: u32) = move _6; - StorageDead(_6); - _0 = Option::::Some(_5); + ((*_1).0: u32) = move _8; + StorageDead(_8); + _0 = Option::::Some(_7); goto -> bb4; } bb4: { - StorageDead(_4); - StorageDead(_5); + StorageDead(_6); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index cc12c0122b7eb..83c9e6c1af26a 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -7,65 +7,67 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { debug self => _1; scope 2 (inlined as iter::range::RangeIteratorImpl>::spec_next) { debug self => _1; - let mut _4: bool; - let _5: u32; - let mut _6: u32; - let mut _7: &u32; - let mut _8: &u32; + let mut _2: &u32; + let mut _3: &u32; + let mut _6: bool; + let _7: u32; + let mut _8: u32; scope 3 { - debug old => _5; + debug old => _7; scope 4 { } } scope 5 (inlined cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _2: u32; - let mut _3: u32; + debug self => _2; + debug other => _3; + let mut _4: u32; + let mut _5: u32; } } } bb0: { - StorageLive(_5); - StorageLive(_4); StorageLive(_7); - StorageLive(_8); + StorageLive(_6); StorageLive(_2); - _2 = ((*_1).0: u32); + _2 = &((*_1).0: u32); StorageLive(_3); - _3 = ((*_1).1: u32); - _4 = Lt(move _2, move _3); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _3 = &((*_1).1: u32); + StorageLive(_4); + _4 = ((*_1).0: u32); + StorageLive(_5); + _5 = ((*_1).1: u32); + _6 = Lt(move _4, move _5); + StorageDead(_5); + StorageDead(_4); + switchInt(move _6) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_8); - StorageDead(_7); + StorageDead(_3); + StorageDead(_2); _0 = Option::::None; goto -> bb4; } bb2: { - StorageDead(_8); - StorageDead(_7); - _5 = ((*_1).0: u32); - StorageLive(_6); - _6 = ::forward_unchecked(_5, const 1_usize) -> [return: bb3, unwind continue]; + StorageDead(_3); + StorageDead(_2); + _7 = ((*_1).0: u32); + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb3, unwind continue]; } bb3: { - ((*_1).0: u32) = move _6; - StorageDead(_6); - _0 = Option::::Some(_5); + ((*_1).0: u32) = move _8; + StorageDead(_8); + _0 = Option::::Some(_7); goto -> bb4; } bb4: { - StorageDead(_4); - StorageDead(_5); + StorageDead(_6); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 312565e45c331..80a470c948248 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -3,9 +3,9 @@ fn ezmap(_1: Option) -> Option { debug x => _1; let mut _0: std::option::Option; - scope 1 (inlined map::) { + scope 1 (inlined map::) { debug slf => _1; - debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:17:12: 17:15]; + debug f => const ZeroSized: {closure@$DIR/simple_option_map.rs:17:12: 17:15}; let mut _2: isize; let _3: i32; let mut _4: i32; @@ -18,6 +18,7 @@ fn ezmap(_1: Option) -> Option { } bb0: { + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } @@ -37,6 +38,7 @@ fn ezmap(_1: Option) -> Option { } bb3: { + StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index ddfd5b0fefc3e..b35d3a105ba1d 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -1,6 +1,6 @@ // MIR for `variant_a::{closure#0}` after PreCodegen -fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2: &&(usize, usize, usize, usize)) -> bool { +fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: &usize; @@ -10,74 +10,74 @@ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2 let _8: &usize; let mut _9: &(usize, usize, usize, usize); let _10: &usize; - let _11: &usize; - let mut _16: bool; - let _17: &usize; - let mut _22: bool; - let _23: &usize; - let mut _28: bool; - let _29: &usize; - let mut _34: &&usize; + let mut _11: &&usize; + let _12: &usize; + let mut _13: &&usize; + let mut _18: bool; + let mut _19: &&usize; + let _20: &usize; + let mut _21: &&usize; + let mut _26: bool; + let mut _27: &&usize; + let _28: &usize; + let mut _29: &&usize; + let mut _34: bool; let mut _35: &&usize; - let mut _36: &&usize; + let _36: &usize; let mut _37: &&usize; - let mut _38: &&usize; - let mut _39: &&usize; - let mut _40: &&usize; - let mut _41: &&usize; scope 1 { debug a => _4; debug b => _6; debug c => _8; debug d => _10; scope 2 (inlined cmp::impls::::le) { - debug self => _34; - debug other => _35; - let mut _12: &usize; - let mut _13: &usize; + debug self => _11; + debug other => _13; + let mut _14: &usize; + let mut _15: &usize; scope 3 (inlined cmp::impls::::le) { - debug self => _12; - debug other => _13; - let mut _14: usize; - let mut _15: usize; + debug self => _14; + debug other => _15; + let mut _16: usize; + let mut _17: usize; } } scope 4 (inlined cmp::impls::::le) { - debug self => _36; - debug other => _37; - let mut _18: &usize; - let mut _19: &usize; + debug self => _19; + debug other => _21; + let mut _22: &usize; + let mut _23: &usize; scope 5 (inlined cmp::impls::::le) { - debug self => _18; - debug other => _19; - let mut _20: usize; - let mut _21: usize; + debug self => _22; + debug other => _23; + let mut _24: usize; + let mut _25: usize; } } scope 6 (inlined cmp::impls::::le) { - debug self => _38; - debug other => _39; - let mut _24: &usize; - let mut _25: &usize; - scope 7 (inlined cmp::impls::::le) { - debug self => _24; - debug other => _25; - let mut _26: usize; - let mut _27: usize; - } - } - scope 8 (inlined cmp::impls::::le) { - debug self => _40; - debug other => _41; + debug self => _27; + debug other => _29; let mut _30: &usize; let mut _31: &usize; - scope 9 (inlined cmp::impls::::le) { + scope 7 (inlined cmp::impls::::le) { debug self => _30; debug other => _31; let mut _32: usize; let mut _33: usize; } } + scope 8 (inlined cmp::impls::::le) { + debug self => _35; + debug other => _37; + let mut _38: &usize; + let mut _39: &usize; + scope 9 (inlined cmp::impls::::le) { + debug self => _38; + debug other => _39; + let mut _40: usize; + let mut _41: usize; + } + } } bb0: { @@ -93,123 +93,147 @@ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2 StorageLive(_10); _9 = deref_copy (*_2); _10 = &((*_9).3: usize); - StorageLive(_16); - StorageLive(_34); - StorageLive(_35); + StorageLive(_18); StorageLive(_11); - _11 = _8; - _12 = deref_copy _4; - _13 = deref_copy _11; + _11 = &_4; + StorageLive(_13); + StorageLive(_12); + _12 = _8; + _13 = &_12; StorageLive(_14); - _14 = (*_12); StorageLive(_15); - _15 = (*_13); - _16 = Le(move _14, move _15); + _14 = deref_copy _4; + _15 = deref_copy _12; + StorageLive(_16); + _16 = (*_14); + StorageLive(_17); + _17 = (*_15); + _18 = Le(move _16, move _17); + StorageDead(_17); + StorageDead(_16); StorageDead(_15); StorageDead(_14); - switchInt(move _16) -> [0: bb1, otherwise: bb2]; + switchInt(move _18) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageDead(_12); + StorageDead(_13); StorageDead(_11); - StorageDead(_35); - StorageDead(_34); goto -> bb4; } bb2: { + StorageDead(_12); + StorageDead(_13); StorageDead(_11); - StorageDead(_35); - StorageDead(_34); - StorageLive(_22); - StorageLive(_36); - StorageLive(_37); - StorageLive(_17); - _17 = _6; - _18 = deref_copy _10; - _19 = deref_copy _17; - StorageLive(_20); - _20 = (*_18); + StorageLive(_26); + StorageLive(_19); + _19 = &_10; StorageLive(_21); - _21 = (*_19); - _22 = Le(move _20, move _21); - StorageDead(_21); - StorageDead(_20); - switchInt(move _22) -> [0: bb3, otherwise: bb8]; + StorageLive(_20); + _20 = _6; + _21 = &_20; + StorageLive(_22); + StorageLive(_23); + _22 = deref_copy _10; + _23 = deref_copy _20; + StorageLive(_24); + _24 = (*_22); + StorageLive(_25); + _25 = (*_23); + _26 = Le(move _24, move _25); + StorageDead(_25); + StorageDead(_24); + StorageDead(_23); + StorageDead(_22); + switchInt(move _26) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_17); - StorageDead(_37); - StorageDead(_36); + StorageDead(_20); + StorageDead(_21); + StorageDead(_19); goto -> bb4; } bb4: { - StorageLive(_28); - StorageLive(_38); - StorageLive(_39); - StorageLive(_23); - _23 = _4; - _24 = deref_copy _8; - _25 = deref_copy _23; - StorageLive(_26); - _26 = (*_24); + StorageLive(_34); StorageLive(_27); - _27 = (*_25); - _28 = Le(move _26, move _27); - StorageDead(_27); - StorageDead(_26); - switchInt(move _28) -> [0: bb5, otherwise: bb6]; + _27 = &_8; + StorageLive(_29); + StorageLive(_28); + _28 = _4; + _29 = &_28; + StorageLive(_30); + StorageLive(_31); + _30 = deref_copy _8; + _31 = deref_copy _28; + StorageLive(_32); + _32 = (*_30); + StorageLive(_33); + _33 = (*_31); + _34 = Le(move _32, move _33); + StorageDead(_33); + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); + switchInt(move _34) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_23); - StorageDead(_39); - StorageDead(_38); + StorageDead(_28); + StorageDead(_29); + StorageDead(_27); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_23); - StorageDead(_39); - StorageDead(_38); + StorageDead(_28); + StorageDead(_29); + StorageDead(_27); + StorageLive(_35); + _35 = &_6; + StorageLive(_37); + StorageLive(_36); + _36 = _10; + _37 = &_36; + StorageLive(_38); + StorageLive(_39); + _38 = deref_copy _6; + _39 = deref_copy _36; StorageLive(_40); + _40 = (*_38); StorageLive(_41); - StorageLive(_29); - _29 = _10; - _30 = deref_copy _6; - _31 = deref_copy _29; - StorageLive(_32); - _32 = (*_30); - StorageLive(_33); - _33 = (*_31); - _0 = Le(move _32, move _33); - StorageDead(_33); - StorageDead(_32); - StorageDead(_29); + _41 = (*_39); + _0 = Le(move _40, move _41); StorageDead(_41); StorageDead(_40); + StorageDead(_39); + StorageDead(_38); + StorageDead(_36); + StorageDead(_37); + StorageDead(_35); goto -> bb7; } bb7: { - StorageDead(_28); + StorageDead(_34); goto -> bb9; } bb8: { - StorageDead(_17); - StorageDead(_37); - StorageDead(_36); + StorageDead(_20); + StorageDead(_21); + StorageDead(_19); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_22); - StorageDead(_16); + StorageDead(_26); + StorageDead(_18); StorageDead(_10); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index 7e70c6290a8b8..80c8cebff45c8 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -1,6 +1,6 @@ // MIR for `variant_b::{closure#0}` after PreCodegen -fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:11:25: 11:41], _2: &&(usize, usize, usize, usize)) -> bool { +fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; 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 2fd669aeeb61d..729841ec5ea8a 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 @@ -19,11 +19,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let _15: usize; - let _16: usize; scope 4 { - debug ((this: std::ops::Range).0: usize) => _15; - debug ((this: std::ops::Range).1: usize) => _16; + debug ((this: std::ops::Range).0: usize) => _3; + debug ((this: std::ops::Range).1: usize) => _4; scope 5 { let _6: usize; scope 6 { @@ -56,8 +54,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 7 (inlined as SliceIndex<[T]>>::get_unchecked_mut::runtime::) { - debug ((this: std::ops::Range).0: usize) => _15; - debug ((this: std::ops::Range).1: usize) => _16; + debug ((this: std::ops::Range).0: usize) => _3; + debug ((this: std::ops::Range).1: usize) => _4; debug slice => _5; scope 8 (inlined ptr::mut_ptr::::len) { debug self => _5; @@ -82,8 +80,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _5 = &raw mut (*_1); StorageLive(_6); StorageLive(_14); - StorageLive(_15); - StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -104,8 +100,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_16); - StorageDead(_15); StorageDead(_14); StorageDead(_6); StorageDead(_5); 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 2fd669aeeb61d..729841ec5ea8a 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 @@ -19,11 +19,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let _15: usize; - let _16: usize; scope 4 { - debug ((this: std::ops::Range).0: usize) => _15; - debug ((this: std::ops::Range).1: usize) => _16; + debug ((this: std::ops::Range).0: usize) => _3; + debug ((this: std::ops::Range).1: usize) => _4; scope 5 { let _6: usize; scope 6 { @@ -56,8 +54,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 7 (inlined as SliceIndex<[T]>>::get_unchecked_mut::runtime::) { - debug ((this: std::ops::Range).0: usize) => _15; - debug ((this: std::ops::Range).1: usize) => _16; + debug ((this: std::ops::Range).0: usize) => _3; + debug ((this: std::ops::Range).1: usize) => _4; debug slice => _5; scope 8 (inlined ptr::mut_ptr::::len) { debug self => _5; @@ -82,8 +80,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _5 = &raw mut (*_1); StorageLive(_6); StorageLive(_14); - StorageLive(_15); - StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -104,8 +100,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_16); - StorageDead(_15); StorageDead(_14); StorageDead(_6); StorageDead(_5); diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 4afe2eda188fb..ac1de7b4c9041 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -7,43 +7,43 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _3: usize; let mut _4: std::ops::Range; let mut _5: std::ops::Range; - let mut _9: std::option::Option; - let mut _12: isize; - let mut _14: usize; - let mut _15: bool; - let mut _17: &impl Fn(usize, &T); - let mut _18: (usize, &T); - let _19: (); - let mut _20: &mut std::ops::Range; + let mut _6: &mut std::ops::Range; + let mut _12: std::option::Option; + let mut _15: isize; + let mut _17: usize; + let mut _18: bool; + let mut _20: &impl Fn(usize, &T); + let mut _21: (usize, &T); + let _22: (); scope 1 { debug iter => _5; - let _13: usize; + let _16: usize; scope 2 { - debug i => _13; - let _16: &T; + debug i => _16; + let _19: &T; scope 3 { - debug x => _16; + debug x => _19; } } scope 5 (inlined iter::range::>::next) { - debug self => _20; + debug self => _6; scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _20; - let mut _8: bool; - let _10: usize; - let mut _11: usize; - let mut _21: &usize; - let mut _22: &usize; + debug self => _6; + let mut _7: &usize; + let mut _8: &usize; + let mut _11: bool; + let _13: usize; + let mut _14: usize; scope 7 { - debug old => _10; + debug old => _13; scope 8 { } } scope 9 (inlined cmp::impls::::lt) { - debug self => _21; - debug other => _22; - let mut _6: usize; - let mut _7: usize; + debug self => _7; + debug other => _8; + let mut _9: usize; + let mut _10: usize; } } } @@ -63,52 +63,55 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb1: { + StorageLive(_12); + _6 = &mut _5; + StorageLive(_13); + StorageLive(_11); + StorageLive(_7); + _7 = &(_5.0: usize); + StorageLive(_8); + _8 = &(_5.1: usize); StorageLive(_9); + _9 = (_5.0: usize); StorageLive(_10); - StorageLive(_8); - StorageLive(_21); - StorageLive(_22); - StorageLive(_6); - _6 = (_5.0: usize); - StorageLive(_7); - _7 = (_5.1: usize); - _8 = Lt(move _6, move _7); - StorageDead(_7); - StorageDead(_6); - switchInt(move _8) -> [0: bb2, otherwise: bb3]; + _10 = (_5.1: usize); + _11 = Lt(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + switchInt(move _11) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_22); - StorageDead(_21); - _9 = Option::::None; + StorageDead(_8); + StorageDead(_7); + _12 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_22); - StorageDead(_21); - _10 = (_5.0: usize); - StorageLive(_11); - _11 = ::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable]; + StorageDead(_8); + StorageDead(_7); + _13 = (_5.0: usize); + StorageLive(_14); + _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; } bb4: { - (_5.0: usize) = move _11; - StorageDead(_11); - _9 = Option::::Some(_10); + (_5.0: usize) = move _14; + StorageDead(_14); + _12 = Option::::Some(_13); goto -> bb5; } bb5: { - StorageDead(_8); - StorageDead(_10); - _12 = discriminant(_9); - switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11]; + StorageDead(_11); + StorageDead(_13); + _15 = discriminant(_12); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; } bb6: { - StorageDead(_9); + StorageDead(_12); StorageDead(_5); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -118,25 +121,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _13 = ((_9 as Some).0: usize); - _14 = Len((*_1)); - _15 = Lt(_13, _14); - assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind unreachable]; + _16 = ((_12 as Some).0: usize); + _17 = Len((*_1)); + _18 = Lt(_16, _17); + assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind unreachable]; } bb9: { - _16 = &(*_1)[_13]; - StorageLive(_17); - _17 = &_2; - StorageLive(_18); - _18 = (_13, _16); - _19 = >::call(move _17, move _18) -> [return: bb10, unwind unreachable]; + _19 = &(*_1)[_16]; + StorageLive(_20); + _20 = &_2; + StorageLive(_21); + _21 = (_16, _19); + _22 = >::call(move _20, move _21) -> [return: bb10, unwind unreachable]; } bb10: { - StorageDead(_18); - StorageDead(_17); - StorageDead(_9); + StorageDead(_21); + StorageDead(_20); + StorageDead(_12); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 48092608d9ca2..3c49ecf95a10c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -7,43 +7,43 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _3: usize; let mut _4: std::ops::Range; let mut _5: std::ops::Range; - let mut _9: std::option::Option; - let mut _12: isize; - let mut _14: usize; - let mut _15: bool; - let mut _17: &impl Fn(usize, &T); - let mut _18: (usize, &T); - let _19: (); - let mut _20: &mut std::ops::Range; + let mut _6: &mut std::ops::Range; + let mut _12: std::option::Option; + let mut _15: isize; + let mut _17: usize; + let mut _18: bool; + let mut _20: &impl Fn(usize, &T); + let mut _21: (usize, &T); + let _22: (); scope 1 { debug iter => _5; - let _13: usize; + let _16: usize; scope 2 { - debug i => _13; - let _16: &T; + debug i => _16; + let _19: &T; scope 3 { - debug x => _16; + debug x => _19; } } scope 5 (inlined iter::range::>::next) { - debug self => _20; + debug self => _6; scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _20; - let mut _8: bool; - let _10: usize; - let mut _11: usize; - let mut _21: &usize; - let mut _22: &usize; + debug self => _6; + let mut _7: &usize; + let mut _8: &usize; + let mut _11: bool; + let _13: usize; + let mut _14: usize; scope 7 { - debug old => _10; + debug old => _13; scope 8 { } } scope 9 (inlined cmp::impls::::lt) { - debug self => _21; - debug other => _22; - let mut _6: usize; - let mut _7: usize; + debug self => _7; + debug other => _8; + let mut _9: usize; + let mut _10: usize; } } } @@ -63,52 +63,55 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb1: { + StorageLive(_12); + _6 = &mut _5; + StorageLive(_13); + StorageLive(_11); + StorageLive(_7); + _7 = &(_5.0: usize); + StorageLive(_8); + _8 = &(_5.1: usize); StorageLive(_9); + _9 = (_5.0: usize); StorageLive(_10); - StorageLive(_8); - StorageLive(_21); - StorageLive(_22); - StorageLive(_6); - _6 = (_5.0: usize); - StorageLive(_7); - _7 = (_5.1: usize); - _8 = Lt(move _6, move _7); - StorageDead(_7); - StorageDead(_6); - switchInt(move _8) -> [0: bb2, otherwise: bb3]; + _10 = (_5.1: usize); + _11 = Lt(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + switchInt(move _11) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_22); - StorageDead(_21); - _9 = Option::::None; + StorageDead(_8); + StorageDead(_7); + _12 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_22); - StorageDead(_21); - _10 = (_5.0: usize); - StorageLive(_11); - _11 = ::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb12]; + StorageDead(_8); + StorageDead(_7); + _13 = (_5.0: usize); + StorageLive(_14); + _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb12]; } bb4: { - (_5.0: usize) = move _11; - StorageDead(_11); - _9 = Option::::Some(_10); + (_5.0: usize) = move _14; + StorageDead(_14); + _12 = Option::::Some(_13); goto -> bb5; } bb5: { - StorageDead(_8); - StorageDead(_10); - _12 = discriminant(_9); - switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11]; + StorageDead(_11); + StorageDead(_13); + _15 = discriminant(_12); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; } bb6: { - StorageDead(_9); + StorageDead(_12); StorageDead(_5); drop(_2) -> [return: bb7, unwind continue]; } @@ -118,25 +121,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _13 = ((_9 as Some).0: usize); - _14 = Len((*_1)); - _15 = Lt(_13, _14); - assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind: bb12]; + _16 = ((_12 as Some).0: usize); + _17 = Len((*_1)); + _18 = Lt(_16, _17); + assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind: bb12]; } bb9: { - _16 = &(*_1)[_13]; - StorageLive(_17); - _17 = &_2; - StorageLive(_18); - _18 = (_13, _16); - _19 = >::call(move _17, move _18) -> [return: bb10, unwind: bb12]; + _19 = &(*_1)[_16]; + StorageLive(_20); + _20 = &_2; + StorageLive(_21); + _21 = (_16, _19); + _22 = >::call(move _20, move _21) -> [return: bb10, unwind: bb12]; } bb10: { - StorageDead(_18); - StorageDead(_17); - StorageDead(_9); + StorageDead(_21); + StorageDead(_20); + StorageDead(_12); goto -> bb1; } 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 549cb4f46a0e2..f3760463fe0c3 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 @@ -7,21 +7,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Rev>; let mut _15: std::iter::Rev>; - let mut _17: std::option::Option<&T>; - let mut _18: isize; - let mut _20: &impl Fn(&T); - let mut _21: (&T,); - let _22: (); - let mut _23: &mut std::iter::Rev>; + let mut _16: &mut std::iter::Rev>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { debug iter => _15; - let _19: &T; + let _20: &T; scope 2 { - debug x => _19; + debug x => _20; } scope 25 (inlined > as Iterator>::next) { - debug self => _23; - let mut _16: &mut std::slice::Iter<'_, T>; + debug self => _16; + let mut _17: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -153,20 +153,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { + StorageLive(_18); + _16 = &mut _15; StorageLive(_17); - StorageLive(_16); - _16 = &mut (_15.0: std::slice::Iter<'_, T>); - _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind unreachable]; + _17 = &mut (_15.0: std::slice::Iter<'_, T>); + _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); + StorageDead(_18); StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -176,18 +177,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _19 = ((_17 as Some).0: &T); - StorageLive(_20); - _20 = &_2; + _20 = ((_18 as Some).0: &T); StorageLive(_21); - _21 = (_19,); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_17); + StorageDead(_18); goto -> bb4; } 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 3cdc49f6056bd..e63f8b89308cf 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 @@ -7,21 +7,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Rev>; let mut _15: std::iter::Rev>; - let mut _17: std::option::Option<&T>; - let mut _18: isize; - let mut _20: &impl Fn(&T); - let mut _21: (&T,); - let _22: (); - let mut _23: &mut std::iter::Rev>; + let mut _16: &mut std::iter::Rev>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { debug iter => _15; - let _19: &T; + let _20: &T; scope 2 { - debug x => _19; + debug x => _20; } scope 25 (inlined > as Iterator>::next) { - debug self => _23; - let mut _16: &mut std::slice::Iter<'_, T>; + debug self => _16; + let mut _17: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -153,20 +153,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { + StorageLive(_18); + _16 = &mut _15; StorageLive(_17); - StorageLive(_16); - _16 = &mut (_15.0: std::slice::Iter<'_, T>); - _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11]; + _17 = &mut (_15.0: std::slice::Iter<'_, T>); + _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); + StorageDead(_18); StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -176,18 +177,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _19 = ((_17 as Some).0: &T); - StorageLive(_20); - _20 = &_2; + _20 = ((_18 as Some).0: &T); StorageLive(_21); - _21 = (_19,); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_17); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index 18a663d9f9e9f..1d3317efd41d4 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 _0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::Constant + // mir::ConstOperand // + span: $DIR/spans.rs:10:5: 10:10 - // + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } + // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } } bb1: { diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index 1c02fb72bcd60..aba66861f7d29 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 _0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::Constant + // mir::ConstOperand // + span: $DIR/spans.rs:10:5: 10:10 - // + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } + // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } } bb1: { diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-abort.mir index 4a3d197849b24..7f3310919cade 100644 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-abort.mir +++ b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` after SimplifyCfg-elaborate-drops -fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { +fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { debug x => _2; let mut _0: &i32; let _3: &i32; diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 4a3d197849b24..7f3310919cade 100644 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` after SimplifyCfg-elaborate-drops -fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { +fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { debug x => _2; let mut _0: &i32; let _3: &i32; 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 fb37bec109a07..ec894fa511a7e 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 @@ -10,7 +10,7 @@ fn main() -> () { let mut _7: &mut i32; let mut _9: &mut i32; let mut _12: *mut i32; - let mut _14: [closure@main::{closure#0}]; + let mut _14: {closure@main::{closure#0}}; let mut _16: for<'a> fn(&'a i32) -> &'a i32; let mut _17: &i32; let _18: &i32; @@ -103,7 +103,7 @@ fn main() -> () { StorageDead(_2); StorageLive(_13); StorageLive(_14); - _14 = [closure@main::{closure#0}]; + _14 = {closure@main::{closure#0}}; Retag(_14); _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); 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 7d3346faba6c6..d89124f699bd8 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 @@ -10,7 +10,7 @@ fn main() -> () { let mut _7: &mut i32; let mut _9: &mut i32; let mut _12: *mut i32; - let mut _14: [closure@main::{closure#0}]; + let mut _14: {closure@main::{closure#0}}; let mut _16: for<'a> fn(&'a i32) -> &'a i32; let mut _17: &i32; let _18: &i32; @@ -103,7 +103,7 @@ fn main() -> () { StorageDead(_2); StorageLive(_13); StorageLive(_14); - _14 = [closure@main::{closure#0}]; + _14 = {closure@main::{closure#0}}; Retag(_14); _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index ca1528b6ab1a4..491db551a7d2b 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -48,6 +48,7 @@ bb0: { StorageLive(_3); + StorageLive(_9); StorageLive(_10); StorageLive(_11); _9 = discriminant(_1); @@ -57,6 +58,7 @@ bb1: { StorageDead(_11); StorageDead(_10); + StorageDead(_9); _5 = discriminant(_3); switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/ssa_unreachable_116212.rs b/tests/mir-opt/ssa_unreachable_116212.rs new file mode 100644 index 0000000000000..f588665876c87 --- /dev/null +++ b/tests/mir-opt/ssa_unreachable_116212.rs @@ -0,0 +1,14 @@ +// Regression test for issue #116212. + +#![feature(never_type)] + +use std::mem::MaybeUninit; + +struct Foo { + x: u8, + y: !, +} + +fn main() { + let foo = unsafe { MaybeUninit::::uninit().assume_init() }; +} diff --git a/tests/run-coverage/unreachable.coverage b/tests/run-coverage/unreachable.coverage new file mode 100644 index 0000000000000..fa0ac9ccfa1c8 --- /dev/null +++ b/tests/run-coverage/unreachable.coverage @@ -0,0 +1,38 @@ + LL| |#![feature(core_intrinsics)] + LL| |#![feature(coverage_attribute)] + LL| |// compile-flags: --edition=2021 + LL| | + LL| |// + LL| |// If we instrument a function for coverage, but all of its counter-increment + LL| |// statements are removed by MIR optimizations, LLVM will think it isn't + LL| |// instrumented and it will disappear from coverage maps and coverage reports. + LL| |// Most MIR opts won't cause this because they tend not to remove statements + LL| |// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends + LL| |// with `TerminatorKind::Unreachable`. + LL| | + LL| |use std::hint::{black_box, unreachable_unchecked}; + LL| | + LL| 0|static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; + LL| | + LL| 0|fn unreachable_function() { + LL| 0| unsafe { unreachable_unchecked() } + LL| 0|} + LL| | + LL| |// Use an intrinsic to more reliably trigger unreachable-propagation. + LL| 0|fn unreachable_intrinsic() { + LL| 0| unsafe { std::intrinsics::unreachable() } + LL| 0|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | if black_box(false) { + LL| | UNREACHABLE_CLOSURE(); + LL| | } + LL| | if black_box(false) { + LL| | unreachable_function(); + LL| | } + LL| | if black_box(false) { + LL| | unreachable_intrinsic(); + LL| | } + LL| |} + diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs new file mode 100644 index 0000000000000..6385bfa160d7d --- /dev/null +++ b/tests/run-coverage/unreachable.rs @@ -0,0 +1,37 @@ +#![feature(core_intrinsics)] +#![feature(coverage_attribute)] +// compile-flags: --edition=2021 + +// +// If we instrument a function for coverage, but all of its counter-increment +// statements are removed by MIR optimizations, LLVM will think it isn't +// instrumented and it will disappear from coverage maps and coverage reports. +// Most MIR opts won't cause this because they tend not to remove statements +// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends +// with `TerminatorKind::Unreachable`. + +use std::hint::{black_box, unreachable_unchecked}; + +static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; + +fn unreachable_function() { + unsafe { unreachable_unchecked() } +} + +// Use an intrinsic to more reliably trigger unreachable-propagation. +fn unreachable_intrinsic() { + unsafe { std::intrinsics::unreachable() } +} + +#[coverage(off)] +fn main() { + if black_box(false) { + UNREACHABLE_CLOSURE(); + } + if black_box(false) { + unreachable_function(); + } + if black_box(false) { + unreachable_intrinsic(); + } +} diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs index b59a65a713f95..5df4c558ee17f 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs @@ -25,8 +25,8 @@ use rustc_hir::def_id::LocalDefId; use rustc_interface::interface::Compiler; use rustc_interface::{Config, Queries}; use rustc_middle::query::queries::mir_borrowck::ProvidedValue; -use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::TyCtxt; +use rustc_middle::util::Providers; use rustc_session::Session; use std::cell::RefCell; use std::collections::HashMap; @@ -110,7 +110,7 @@ impl rustc_driver::Callbacks for CompilerCalls { } } -fn override_queries(_session: &Session, local: &mut Providers, _external: &mut ExternProviders) { +fn override_queries(_session: &Session, local: &mut Providers) { local.mir_borrowck = mir_borrowck; } diff --git a/tests/run-make/const_fn_mir/Makefile b/tests/run-make/const_fn_mir/Makefile index 6d72c12272303..3399446130d74 100644 --- a/tests/run-make/const_fn_mir/Makefile +++ b/tests/run-make/const_fn_mir/Makefile @@ -3,9 +3,4 @@ include ../tools.mk all: $(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/dump.mir dump.mir -else - $(DIFF) dump.mir "$(TMPDIR)"/dump.mir -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/dump.mir dump.mir diff --git a/tests/run-make/incr-foreign-head-span/Makefile b/tests/run-make/incr-foreign-head-span/Makefile index 9d6102cdd72dc..9be4b0f601c30 100644 --- a/tests/run-make/incr-foreign-head-span/Makefile +++ b/tests/run-make/incr-foreign-head-span/Makefile @@ -15,7 +15,7 @@ INCR=$(TMPDIR)/incr all: cp first_crate.rs second_crate.rs $(TMPDIR) $(RUSTC) $(TMPDIR)/first_crate.rs -C incremental=$(INCR) --target $(TARGET) --crate-type lib - $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first-crate=$(TMPDIR) --crate-type lib + $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first_crate=$(TMPDIR)/libfirst_crate.rlib --crate-type lib rm $(TMPDIR)/first_crate.rs $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib diff --git a/tests/run-make/issue-71519/Makefile b/tests/run-make/issue-71519/Makefile deleted file mode 100644 index 0ee83328bb689..0000000000000 --- a/tests/run-make/issue-71519/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -# ignore-msvc -# needs-rust-lld -# ignore-s390x lld does not yet support s390x as target -all: - RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt - $(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt diff --git a/tests/run-make/issue-71519/main.rs b/tests/run-make/issue-71519/main.rs deleted file mode 100644 index f8d09e8975330..0000000000000 --- a/tests/run-make/issue-71519/main.rs +++ /dev/null @@ -1,4 +0,0 @@ -// test linking using cc with rust-lld injected into search path as ld -// see rust-lang/rust#71519 for more info - -fn main() {} diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout index f5981045b03db..38a3965f0c53d 100644 --- a/tests/run-make/issue-88756-default-output/output-default.stdout +++ b/tests/run-make/issue-88756-default-output/output-default.stdout @@ -133,9 +133,6 @@ Options: Path string to force loading static files from in output pages. If not set, uses combinations of '../' to reach the documentation root. - --disable-per-crate-search - disables generating the crate selector on the search - box --persist-doctests PATH Directory to persist doctest executables into --show-coverage diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile index d0cf836bcdfcc..757ca6995350f 100644 --- a/tests/run-make/macos-deployment-target/Makefile +++ b/tests/run-make/macos-deployment-target/Makefile @@ -9,12 +9,12 @@ include ../tools.mk ifeq ($(strip $(shell uname -m)),arm64) GREP_PATTERN = "minos 11.0" else - GREP_PATTERN = "version 10.9" + GREP_PATTERN = "version 10.13" endif OUT_FILE=$(TMPDIR)/with_deployment_target.dylib all: - env MACOSX_DEPLOYMENT_TARGET=10.9 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE) + env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE) # XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11). # They also use different load commands, so we let that change with each too. The aarch64 check # isn't as robust as the x86 one, but testing both seems unneeded. diff --git a/tests/run-make/metadata-dep-info/Makefile b/tests/run-make/metadata-dep-info/Makefile index f9043f214338c..d48cbe0f29505 100644 --- a/tests/run-make/metadata-dep-info/Makefile +++ b/tests/run-make/metadata-dep-info/Makefile @@ -1,11 +1,5 @@ include ../tools.mk -ifdef RUSTC_BLESS_TEST - RUSTC_TEST_OP = cp -else - RUSTC_TEST_OP = $(DIFF) -endif - all: $(RUSTC) --emit=metadata,dep-info --crate-type lib dash-separated.rs -C extra-filename=_something-extra # Strip TMPDIR since it is a machine specific absolute path diff --git a/tests/run-make/overwrite-input/Makefile b/tests/run-make/overwrite-input/Makefile index c62b5aab190db..721bf62b26b5d 100644 --- a/tests/run-make/overwrite-input/Makefile +++ b/tests/run-make/overwrite-input/Makefile @@ -3,11 +3,5 @@ include ../tools.mk all: $(RUSTC) main.rs -o main.rs 2> $(TMPDIR)/file.stderr || echo "failed successfully" $(RUSTC) main.rs -o . 2> $(TMPDIR)/folder.stderr || echo "failed successfully" - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/file.stderr file.stderr - cp "$(TMPDIR)"/folder.stderr folder.stderr -else - $(DIFF) file.stderr "$(TMPDIR)"/file.stderr - $(DIFF) folder.stderr "$(TMPDIR)"/folder.stderr -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/file.stderr file.stderr + $(RUSTC_TEST_OP) "$(TMPDIR)"/folder.stderr folder.stderr diff --git a/tests/run-make/raw-dylib-alt-calling-convention/Makefile b/tests/run-make/raw-dylib-alt-calling-convention/Makefile index 1744c431f9c99..14d23a5d20106 100644 --- a/tests/run-make/raw-dylib-alt-calling-convention/Makefile +++ b/tests/run-make/raw-dylib-alt-calling-convention/Makefile @@ -16,17 +16,9 @@ else endif "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.txt output.txt -else - $(DIFF) output.txt "$(TMPDIR)"/output.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt ifdef IS_MSVC "$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt -else - $(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/output.msvc.txt output.msvc.txt endif diff --git a/tests/run-make/raw-dylib-import-name-type/Makefile b/tests/run-make/raw-dylib-import-name-type/Makefile index 67152329807cf..901d3e861c21a 100644 --- a/tests/run-make/raw-dylib-import-name-type/Makefile +++ b/tests/run-make/raw-dylib-import-name-type/Makefile @@ -14,9 +14,4 @@ else $(CC) "$(TMPDIR)"/extern.obj extern.gnu.def --no-leading-underscore -shared -o "$(TMPDIR)"/extern.dll endif "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.txt output.txt -else - $(DIFF) output.txt "$(TMPDIR)"/output.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile index 6d1d04bfd37d2..195b5fda56fd3 100644 --- a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile +++ b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile @@ -27,9 +27,4 @@ else $(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll endif $(call RUN,driver) > "$(TMPDIR)"/output.txt - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.txt output.txt -else - $(DIFF) output.txt "$(TMPDIR)"/output.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt diff --git a/tests/run-make/raw-dylib-link-ordinal/Makefile b/tests/run-make/raw-dylib-link-ordinal/Makefile index 374a0b59de322..49e959cdb5b8e 100644 --- a/tests/run-make/raw-dylib-link-ordinal/Makefile +++ b/tests/run-make/raw-dylib-link-ordinal/Makefile @@ -14,9 +14,4 @@ else $(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll endif "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.txt output.txt -else - $(DIFF) output.txt "$(TMPDIR)"/output.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile index 178c15ab3dee4..70e4de62c1a9e 100644 --- a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile +++ b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile @@ -15,9 +15,4 @@ else $(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll endif "$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/actual_output.txt expected_output.txt -else - $(DIFF) expected_output.txt "$(TMPDIR)"/actual_output.txt -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/actual_output.txt expected_output.txt diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile index 1f2812cb08792..9ba077b18547e 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile @@ -3,7 +3,7 @@ include ../tools.mk # ignore-cross-compile # only-linux -# Make sure -Zpacked_bundled_libs-like behavior activates with whole-archive. +# Make sure -Zpacked_bundled_libs-like behavior activates with +bundle,+whole-archive. # We're using the llvm-nm instead of the system nm to ensure it is compatible # with the LLVM bitcode generated by rustc. @@ -11,7 +11,7 @@ NM = "$(LLVM_BIN_DIR)"/llvm-nm all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) $(call NATIVE_STATICLIB,native_dep_4) # test cfg with packed bundle - $(RUSTC) rust_dep_cfg.rs --crate-type=rlib -Zpacked_bundled_libs + $(RUSTC) rust_dep_cfg.rs --crate-type=rlib $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep_cfg.rlib --crate-type=staticlib --cfg should_add $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_1.a" $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_2.a" diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs index abd846b6862d1..bde9b739de6a3 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs @@ -1,5 +1,3 @@ -#![feature(packed_bundled_libs)] - #[link(name = "native_dep_1", kind = "static", modifiers = "+whole-archive,+bundle")] extern "C" {} diff --git a/tests/run-make/silly-file-names/Makefile b/tests/run-make/silly-file-names/Makefile new file mode 100644 index 0000000000000..e51266c0880b0 --- /dev/null +++ b/tests/run-make/silly-file-names/Makefile @@ -0,0 +1,12 @@ +# ignore-cross-compile we need to execute the binary +# ignore-windows we create files with < and > in their names + +include ../tools.mk + +all: + echo '"comes from a file with a name that begins with <"' > "$(TMPDIR)/"' > "$(TMPDIR)/trailing-gt>" + cp silly-file-names.rs "$(TMPDIR)/silly-file-names.rs" + $(RUSTC) "$(TMPDIR)/silly-file-names.rs" -o "$(TMPDIR)/silly-file-names" + "$(TMPDIR)/silly-file-names" > "$(TMPDIR)/silly-file-names.run.stdout" + $(RUSTC_TEST_OP) "$(TMPDIR)/silly-file-names.run.stdout" silly-file-names.run.stdout diff --git a/tests/run-make/silly-file-names/silly-file-names.rs b/tests/run-make/silly-file-names/silly-file-names.rs new file mode 100644 index 0000000000000..a200820914130 --- /dev/null +++ b/tests/run-make/silly-file-names/silly-file-names.rs @@ -0,0 +1,4 @@ +fn main() { + println!(include!("")); +} diff --git a/tests/run-make/silly-file-names/silly-file-names.run.stdout b/tests/run-make/silly-file-names/silly-file-names.run.stdout new file mode 100644 index 0000000000000..fbc4c89e0f017 --- /dev/null +++ b/tests/run-make/silly-file-names/silly-file-names.run.stdout @@ -0,0 +1,2 @@ +comes from a file with a name that begins with < +comes from a file with a name that ends with > diff --git a/tests/run-make/tools.mk b/tests/run-make/tools.mk index 6121a91e9203f..1d4e911138920 100644 --- a/tests/run-make/tools.mk +++ b/tests/run-make/tools.mk @@ -21,6 +21,28 @@ CGREP := "$(S)/src/etc/cat-and-grep.sh" # diff with common flags for multi-platform diffs against text output DIFF := diff -u --strip-trailing-cr +# With RUSTC_TEST_OP you can elegantly support blessing of run-make tests. Do +# like this in a Makefile recipe: +# +# "$(TMPDIR)"/your-test > "$(TMPDIR)"/your-test.run.stdout +# $(RUSTC_TEST_OP) "$(TMPDIR)"/your-test.run.stdout your-test.run.stdout +# +# When running the test normally with +# +# ./x test tests/run-make/your-test +# +# the actual output will be diffed against the expected output. When running in +# bless-mode with +# +# ./x test --bless tests/run-make/your-test +# +# the actual output will be blessed as the expected output. +ifdef RUSTC_BLESS_TEST + RUSTC_TEST_OP = cp +else + RUSTC_TEST_OP = $(DIFF) +endif + # Some of the Rust CI platforms use `/bin/dash` to run `shell` script in # Makefiles. Other platforms, including many developer platforms, default to # `/bin/bash`. (In many cases, `make` is actually using `/bin/sh`, but `sh` diff --git a/tests/run-make/unknown-mod-stdin/Makefile b/tests/run-make/unknown-mod-stdin/Makefile index c1931765382e8..313b0ba837e83 100644 --- a/tests/run-make/unknown-mod-stdin/Makefile +++ b/tests/run-make/unknown-mod-stdin/Makefile @@ -4,12 +4,5 @@ include ../tools.mk all: echo 'mod unknown;' | $(RUSTC) --crate-type rlib - >$(TMPDIR)/unknown-mod.stdout 2>$(TMPDIR)/unknown-mod.stderr || echo "failed successfully" - -# Bless like this: RUSTC_BLESS_TEST=1 ./x.py test tests/run-make/unknown-mod-stdin -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/unknown-mod.stdout unknown-mod.stdout - cp "$(TMPDIR)"/unknown-mod.stderr unknown-mod.stderr -else - $(DIFF) unknown-mod.stdout "$(TMPDIR)"/unknown-mod.stdout - $(DIFF) unknown-mod.stderr "$(TMPDIR)"/unknown-mod.stderr -endif + $(RUSTC_TEST_OP) "$(TMPDIR)"/unknown-mod.stdout unknown-mod.stdout + $(RUSTC_TEST_OP) "$(TMPDIR)"/unknown-mod.stderr unknown-mod.stderr diff --git a/tests/rustdoc-gui/default-settings.goml b/tests/rustdoc-gui/default-settings.goml index 3466f3693f908..ff4abb65c0286 100644 --- a/tests/rustdoc-gui/default-settings.goml +++ b/tests/rustdoc-gui/default-settings.goml @@ -5,4 +5,4 @@ go-to: "file://" + |DOC_PATH| + "/settings/index.html" // Wait a bit to be sure the default theme is applied. // If the theme isn't applied, the command will time out. -wait-for-css: ("body", {"background-color": "rgb(15, 20, 25)"}) +wait-for-css: ("body", {"background-color": "#0f1419"}) diff --git a/tests/rustdoc-js/impl-trait.js b/tests/rustdoc-js/impl-trait.js index 710e594b54774..00d67d639bd08 100644 --- a/tests/rustdoc-js/impl-trait.js +++ b/tests/rustdoc-js/impl-trait.js @@ -1,3 +1,4 @@ +// exact-check // ignore-order const EXPECTED = [ @@ -20,9 +21,16 @@ const EXPECTED = [ { 'query': '-> Aaaaaaa', 'others': [ - { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, - { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' }, { 'path': 'impl_trait', 'name': 'bbbbbbb' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' }, + ], + }, + { + 'query': '-> Bbbbbbb', + 'others': [ + { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' }, ], }, { @@ -31,13 +39,14 @@ const EXPECTED = [ { 'path': 'impl_trait', 'name': 'Aaaaaaa' }, ], 'in_args': [ - { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, ], 'returned': [ - { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, - { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' }, { 'path': 'impl_trait', 'name': 'bbbbbbb' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' }, + { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' }, ], }, ]; diff --git a/tests/rustdoc-js/impl-trait.rs b/tests/rustdoc-js/impl-trait.rs index fb8869b46f3d4..d20fdd60ec965 100644 --- a/tests/rustdoc-js/impl-trait.rs +++ b/tests/rustdoc-js/impl-trait.rs @@ -1,6 +1,9 @@ pub trait Aaaaaaa {} +pub trait Bbbbbbb {} + impl Aaaaaaa for () {} +impl Bbbbbbb for () {} pub fn bbbbbbb() -> impl Aaaaaaa { () @@ -18,4 +21,7 @@ impl Ccccccc { pub fn fffffff(&self, x: impl Aaaaaaa) -> impl Aaaaaaa { x } + pub fn ggggggg(&self) -> impl Aaaaaaa + Bbbbbbb { + () + } } diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr index 4f2ded78c29fa..ad049804213d3 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr @@ -28,6 +28,8 @@ LL | | LL | | /// main; LL | | /// ``` | |_______^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr index 83e0d3962ca1a..b25849f25b455 100644 --- a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr +++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr @@ -22,6 +22,7 @@ LL | /// [1] | ^ no item named `1` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/rustdoc-ui/issue-102467.rs b/tests/rustdoc-ui/issue-102467.rs new file mode 100644 index 0000000000000..bff876e41d66a --- /dev/null +++ b/tests/rustdoc-ui/issue-102467.rs @@ -0,0 +1,15 @@ +// Regression test for . +// It ensures that the expected error is displayed. + +#![feature(associated_const_equality)] + +trait T { + type A: S = 34>; + //~^ ERROR associated type bindings are not allowed here +} + +trait S { + const C: i32; +} + +fn main() {} diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr new file mode 100644 index 0000000000000..a337293f7a055 --- /dev/null +++ b/tests/rustdoc-ui/issue-102467.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102467.rs:7:17 + | +LL | type A: S = 34>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr index b63176c914905..4d3f9f5bced77 100644 --- a/tests/rustdoc-ui/issues/issue-105742.stderr +++ b/tests/rustdoc-ui/issues/issue-105742.stderr @@ -169,6 +169,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | ::Item<'a>, @@ -185,6 +186,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | ::Item, @@ -201,6 +203,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item<'a>, @@ -217,6 +220,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item, @@ -233,6 +237,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item<'a>> as SVec>::Item, @@ -249,6 +254,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, @@ -265,6 +271,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item> as SVec>::Item<'a>, @@ -281,6 +288,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, @@ -327,6 +335,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | ::Item<'a>, @@ -343,6 +352,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | ::Item, @@ -359,6 +369,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item<'a>, @@ -375,6 +386,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item, @@ -391,6 +403,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item<'a>> as SVec>::Item, @@ -407,6 +420,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, @@ -423,6 +437,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Item<'a, T>; | ^^^^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | Output = ::Item> as SVec>::Item<'a>, @@ -439,6 +454,7 @@ note: associated type defined here, with 1 generic parameter: `T` | LL | type Item<'a, T>; | ^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs index c34ea0567a9d4..ce94a06c39eae 100644 --- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs +++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs @@ -1,12 +1,7 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes #![deny(unknown_lints)] //~^ NOTE defined here #![allow(rustdoc::missing_doc_code_examples)] //~^ ERROR unknown lint -//~| ERROR unknown lint -//~| ERROR unknown lint //~| NOTE lint is unstable -//~| NOTE lint is unstable -//~| NOTE lint is unstable -//~| NOTE see issue -//~| NOTE see issue //~| NOTE see issue diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr index 326dcfe3bdef0..b8a08e9431276 100644 --- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr +++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr @@ -1,5 +1,5 @@ error: unknown lint: `rustdoc::missing_doc_code_examples` - --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1 + --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1 | LL | #![allow(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,30 +8,10 @@ LL | #![allow(rustdoc::missing_doc_code_examples)] = note: see issue #101730 for more information = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable note: the lint level is defined here - --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9 + --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:2:9 | LL | #![deny(unknown_lints)] | ^^^^^^^^^^^^^ -error: unknown lint: `rustdoc::missing_doc_code_examples` - --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1 - | -LL | #![allow(rustdoc::missing_doc_code_examples)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `rustdoc::missing_doc_code_examples` lint is unstable - = note: see issue #101730 for more information - = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable - -error: unknown lint: `rustdoc::missing_doc_code_examples` - --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1 - | -LL | #![allow(rustdoc::missing_doc_code_examples)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `rustdoc::missing_doc_code_examples` lint is unstable - = note: see issue #101730 for more information - = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable - -error: aborting due to 3 previous errors +error: aborting due to previous error diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index 83822f778d0f4..2b4e491b1fe9c 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -302,6 +302,7 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: or `None` if it isn't. to this: or `None\` if it isn't. + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -321,6 +322,7 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: `on_event` should be called. to this: `on_event\` should be called. + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -340,6 +342,7 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: [`rebuild_interest_cache`][rebuild] is called after the value of the max to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:349:56 diff --git a/tests/rustdoc/issue-25001.rs b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs similarity index 94% rename from tests/rustdoc/issue-25001.rs rename to tests/rustdoc/anchor-id-duplicate-method-name-25001.rs index 268fae59496ac..ffb0765d3c3f6 100644 --- a/tests/rustdoc/issue-25001.rs +++ b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/25001 +#![crate_name="issue_25001"] + // @has issue_25001/struct.Foo.html pub struct Foo(T); diff --git a/tests/rustdoc/issue-15169.rs b/tests/rustdoc/anchor-id-trait-method-15169.rs similarity index 56% rename from tests/rustdoc/issue-15169.rs rename to tests/rustdoc/anchor-id-trait-method-15169.rs index e525d85e21ec0..26bb59c1875fd 100644 --- a/tests/rustdoc/issue-15169.rs +++ b/tests/rustdoc/anchor-id-trait-method-15169.rs @@ -1,3 +1,7 @@ // @has issue_15169/struct.Foo.html '//*[@id="method.eq"]' 'fn eq' + +// https://github.com/rust-lang/rust/issues/15169 +#![crate_name="issue_15169"] + #[derive(PartialEq)] pub struct Foo; diff --git a/tests/rustdoc/issue-28478.rs b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs similarity index 92% rename from tests/rustdoc/issue-28478.rs rename to tests/rustdoc/anchor-id-trait-tymethod-28478.rs index 497276e6826a1..5685040dc1e1b 100644 --- a/tests/rustdoc/issue-28478.rs +++ b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/28478 +#![crate_name="issue_28478"] + #![feature(associated_type_defaults)] // @has issue_28478/trait.Bar.html diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/assoc-type-bindings-20646.rs similarity index 90% rename from tests/rustdoc/issue-20646.rs rename to tests/rustdoc/assoc-type-bindings-20646.rs index b2ee9c26014b3..375b5b5b23ea5 100644 --- a/tests/rustdoc/issue-20646.rs +++ b/tests/rustdoc/assoc-type-bindings-20646.rs @@ -1,6 +1,8 @@ // aux-build:issue-20646.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20646 +#![crate_name="issue_20646"] #![feature(associated_types)] extern crate issue_20646; diff --git a/tests/rustdoc/auxiliary/enum-variant.rs b/tests/rustdoc/auxiliary/enum-variant.rs new file mode 100644 index 0000000000000..90c71b863290d --- /dev/null +++ b/tests/rustdoc/auxiliary/enum-variant.rs @@ -0,0 +1,24 @@ +#![crate_name = "bar"] + +pub enum E { + A = 12, + B, + C = 1245, +} + +pub enum F { + A, + B, +} + +#[repr(u32)] +pub enum G { + A = 12, + B, + C(u32), +} + +pub enum H { + A, + C(u32), +} diff --git a/tests/rustdoc/issue-21474.rs b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs similarity index 73% rename from tests/rustdoc/issue-21474.rs rename to tests/rustdoc/deduplicate-glob-import-impl-21474.rs index 5de26abace6fa..2a675b4b6ef54 100644 --- a/tests/rustdoc/issue-21474.rs +++ b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/21474 +#![crate_name="issue_21474"] + pub use inner::*; mod inner { diff --git a/tests/rustdoc/issue-22025.rs b/tests/rustdoc/deduplicate-trait-impl-22025.rs similarity index 59% rename from tests/rustdoc/issue-22025.rs rename to tests/rustdoc/deduplicate-trait-impl-22025.rs index a721a15f463b4..65a556e3a70f1 100644 --- a/tests/rustdoc/issue-22025.rs +++ b/tests/rustdoc/deduplicate-trait-impl-22025.rs @@ -1,6 +1,9 @@ // aux-build:issue-22025.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/22025 +#![crate_name="issue_22025"] + extern crate issue_22025; pub use issue_22025::foo::{Foo, Bar}; diff --git a/tests/rustdoc/issue-19190-2.rs b/tests/rustdoc/deref-methods-19190-foreign-type.rs similarity index 77% rename from tests/rustdoc/issue-19190-2.rs rename to tests/rustdoc/deref-methods-19190-foreign-type.rs index b6416e2e5b97e..c8326992115c7 100644 --- a/tests/rustdoc/issue-19190-2.rs +++ b/tests/rustdoc/deref-methods-19190-foreign-type.rs @@ -1,3 +1,7 @@ +// https://github.com/rust-lang/rust/issues/19190 + +#![crate_name="issue_19190_2"] + use std::ops::Deref; pub struct Bar; diff --git a/tests/rustdoc/issue-19190-3.rs b/tests/rustdoc/deref-methods-19190-inline.rs similarity index 90% rename from tests/rustdoc/issue-19190-3.rs rename to tests/rustdoc/deref-methods-19190-inline.rs index 4d34ce6509fe3..619b268d68b39 100644 --- a/tests/rustdoc/issue-19190-3.rs +++ b/tests/rustdoc/deref-methods-19190-inline.rs @@ -1,6 +1,9 @@ // aux-build:issue-19190-3.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/19190 +#![crate_name="issue_19190_3"] + extern crate issue_19190_3; use std::ops::Deref; diff --git a/tests/rustdoc/issue-19190.rs b/tests/rustdoc/deref-methods-19190.rs similarity index 86% rename from tests/rustdoc/issue-19190.rs rename to tests/rustdoc/deref-methods-19190.rs index 2046273e2c1ba..4c274d82ff785 100644 --- a/tests/rustdoc/issue-19190.rs +++ b/tests/rustdoc/deref-methods-19190.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/19190 +#![crate_name="issue_19190"] + use std::ops::Deref; pub struct Foo; diff --git a/tests/rustdoc/issue-13698.rs b/tests/rustdoc/doc-hidden-method-13698.rs similarity index 81% rename from tests/rustdoc/issue-13698.rs rename to tests/rustdoc/doc-hidden-method-13698.rs index 3046a8a28627d..f1bd6e73babdd 100644 --- a/tests/rustdoc/issue-13698.rs +++ b/tests/rustdoc/doc-hidden-method-13698.rs @@ -1,6 +1,9 @@ // aux-build:issue-13698.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/13698 +#![crate_name="issue_13698"] + extern crate issue_13698; pub struct Foo; diff --git a/tests/rustdoc/issue-18199.rs b/tests/rustdoc/doc-test-attr-18199.rs similarity index 79% rename from tests/rustdoc/issue-18199.rs rename to tests/rustdoc/doc-test-attr-18199.rs index 9cc58b162f37e..c9d2235321c87 100644 --- a/tests/rustdoc/issue-18199.rs +++ b/tests/rustdoc/doc-test-attr-18199.rs @@ -1,4 +1,5 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/18199 #![doc(test(attr(feature(staged_api))))] diff --git a/tests/rustdoc/doctest-hide-empty-line-23106.rs b/tests/rustdoc/doctest-hide-empty-line-23106.rs new file mode 100644 index 0000000000000..8e1e2cf098cf2 --- /dev/null +++ b/tests/rustdoc/doctest-hide-empty-line-23106.rs @@ -0,0 +1,10 @@ +// compile-flags:--test + +// https://github.com/rust-lang/rust/issues/23106 +#![crate_name="issue_23106"] + +/// ``` +/// # +/// ``` +pub fn main() { +} diff --git a/tests/rustdoc/issue-23744.rs b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs similarity index 76% rename from tests/rustdoc/issue-23744.rs rename to tests/rustdoc/doctest-markdown-inline-parse-23744.rs index 642817396b2a0..128e2daba071a 100644 --- a/tests/rustdoc/issue-23744.rs +++ b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs @@ -1,5 +1,8 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/23744 +#![crate_name="issue_23744"] + /// Example of rustdoc incorrectly parsing ```rust,should_panic. /// /// ```should_panic diff --git a/tests/rustdoc/issue-25944.rs b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs similarity index 63% rename from tests/rustdoc/issue-25944.rs rename to tests/rustdoc/doctest-multi-line-string-literal-25944.rs index 49625294bbea0..eec796e4fbf29 100644 --- a/tests/rustdoc/issue-25944.rs +++ b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs @@ -1,5 +1,8 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/25944 +#![crate_name="issue_25944"] + /// ``` /// let a = r#" /// foo diff --git a/tests/rustdoc/issue-15347.rs b/tests/rustdoc/document-hidden-items-15347.rs similarity index 61% rename from tests/rustdoc/issue-15347.rs rename to tests/rustdoc/document-hidden-items-15347.rs index e93d74011681b..d8a760e566602 100644 --- a/tests/rustdoc/issue-15347.rs +++ b/tests/rustdoc/document-hidden-items-15347.rs @@ -1,4 +1,7 @@ // compile-flags: -Z unstable-options --document-hidden-items +// https://github.com/rust-lang/rust/issues/15347 + +#![crate_name="issue_15347"] // @has issue_15347/fn.foo.html #[doc(hidden)] diff --git a/tests/rustdoc/enum-variant-value.rs b/tests/rustdoc/enum-variant-value.rs new file mode 100644 index 0000000000000..c306736bfe919 --- /dev/null +++ b/tests/rustdoc/enum-variant-value.rs @@ -0,0 +1,117 @@ +// This test ensures that the variant value is displayed with underscores but without +// a type name at the end. + +// aux-build:enum-variant.rs + +#![crate_name = "foo"] + +extern crate bar; + +// In this case, since all variants are C-like variants and at least one of them +// has its value set, we display values for all of them. + +// @has 'foo/enum.A.html' +// @has - '//*[@class="rust item-decl"]/code' 'A = 12,' +// @has - '//*[@class="rust item-decl"]/code' 'B = 13,' +// @has - '//*[@class="rust item-decl"]/code' 'C = 1_245,' +// @matches - '//*[@id="variant.A"]/h3' '^A = 12$' +// @matches - '//*[@id="variant.B"]/h3' '^B = 13$' +// @matches - '//*[@id="variant.C"]/h3' '^C = 1_245$' +pub enum A { + A = 12, + B, + C = 1245, +} + +// In this case, all variants are C-like variants but none of them has its value set. +// Therefore we don't display values. + +// @has 'foo/enum.B.html' +// @has - '//*[@class="rust item-decl"]/code' 'A,' +// @has - '//*[@class="rust item-decl"]/code' 'B,' +// @matches - '//*[@id="variant.A"]/h3' '^A$' +// @matches - '//*[@id="variant.B"]/h3' '^B$' +pub enum B { + A, + B, +} + +// In this case, not all variants are C-like variants so we don't display values. + +// @has 'foo/enum.C.html' +// @has - '//*[@class="rust item-decl"]/code' 'A = 12,' +// @has - '//*[@class="rust item-decl"]/code' 'B,' +// @has - '//*[@class="rust item-decl"]/code' 'C(u32),' +// @matches - '//*[@id="variant.A"]/h3' '^A = 12$' +// @matches - '//*[@id="variant.B"]/h3' '^B$' +// @has - '//*[@id="variant.C"]/h3' 'C(u32)' +#[repr(u32)] +pub enum C { + A = 12, + B, + C(u32), +} + +// In this case, not all variants are C-like variants and no C-like variant has its +// value set, so we don't display values. + +// @has 'foo/enum.D.html' +// @has - '//*[@class="rust item-decl"]/code' 'A,' +// @has - '//*[@class="rust item-decl"]/code' 'C(u32),' +// @matches - '//*[@id="variant.A"]/h3' '^A$' +// @has - '//*[@id="variant.C"]/h3' 'C(u32)' +pub enum D { + A, + C(u32), +} + +// @has 'foo/enum.E.html' +// @has - '//*[@class="rust item-decl"]/code' 'A = 12,' +// @has - '//*[@class="rust item-decl"]/code' 'B = 13,' +// @has - '//*[@class="rust item-decl"]/code' 'C = 1_245,' +// @matches - '//*[@id="variant.A"]/h3' '^A = 12$' +// @matches - '//*[@id="variant.B"]/h3' '^B = 13$' +// @matches - '//*[@id="variant.C"]/h3' '^C = 1_245$' +pub use bar::E; + +// @has 'foo/enum.F.html' +// @has - '//*[@class="rust item-decl"]/code' 'A,' +// @has - '//*[@class="rust item-decl"]/code' 'B,' +// @matches - '//*[@id="variant.A"]/h3' '^A$' +// @matches - '//*[@id="variant.B"]/h3' '^B$' +pub use bar::F; + +// @has 'foo/enum.G.html' +// @has - '//*[@class="rust item-decl"]/code' 'A = 12,' +// @has - '//*[@class="rust item-decl"]/code' 'B,' +// @has - '//*[@class="rust item-decl"]/code' 'C(u32),' +// @matches - '//*[@id="variant.A"]/h3' '^A = 12$' +// @matches - '//*[@id="variant.B"]/h3' '^B$' +// @has - '//*[@id="variant.C"]/h3' 'C(u32)' +pub use bar::G; + +// @has 'foo/enum.H.html' +// @has - '//*[@class="rust item-decl"]/code' 'A,' +// @has - '//*[@class="rust item-decl"]/code' 'C(u32),' +// @matches - '//*[@id="variant.A"]/h3' '^A$' +// @has - '//*[@id="variant.C"]/h3' 'C(u32)' +pub use bar::H; + +// Testing more complex cases. +pub const X: isize = 2; +// @has 'foo/enum.I.html' +// @has - '//*[@class="rust item-decl"]/code' 'A = 2,' +// @has - '//*[@class="rust item-decl"]/code' 'B = 4,' +// @has - '//*[@class="rust item-decl"]/code' 'C = 9,' +// @has - '//*[@class="rust item-decl"]/code' 'D = -1,' +// @matches - '//*[@id="variant.A"]/h3' '^A = 2$' +// @matches - '//*[@id="variant.B"]/h3' '^B = 4$' +// @matches - '//*[@id="variant.C"]/h3' '^C = 9$' +// @matches - '//*[@id="variant.D"]/h3' '^D = -1$' +#[repr(isize)] +pub enum I { + A = X, + B = X * 2, + C = Self::B as isize + X + 3, + D = -1, +} diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/extern-fn-22038.rs similarity index 87% rename from tests/rustdoc/issue-22038.rs rename to tests/rustdoc/extern-fn-22038.rs index de6cc78707c6d..72d39c32a1c64 100644 --- a/tests/rustdoc/issue-22038.rs +++ b/tests/rustdoc/extern-fn-22038.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/22038 +#![crate_name="issue_22038"] + extern "C" { // @has issue_22038/fn.foo1.html \ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()' diff --git a/tests/rustdoc/issue-12834.rs b/tests/rustdoc/highlight-invalid-rust-12834.rs similarity index 80% rename from tests/rustdoc/issue-12834.rs rename to tests/rustdoc/highlight-invalid-rust-12834.rs index 9605a1e78c105..f8acc5002648f 100644 --- a/tests/rustdoc/issue-12834.rs +++ b/tests/rustdoc/highlight-invalid-rust-12834.rs @@ -1,6 +1,8 @@ // Tests that failing to syntax highlight a rust code-block doesn't cause // rustdoc to fail, while still rendering the code-block (without highlighting). +// https://github.com/rust-lang/rust/issues/12834 +#![crate_name="issue_12834"] #![allow(rustdoc::invalid_rust_codeblocks)] // @has issue_12834/fn.foo.html diff --git a/tests/rustdoc/issue-28927.rs b/tests/rustdoc/ice-reexport-crate-root-28927.rs similarity index 65% rename from tests/rustdoc/issue-28927.rs rename to tests/rustdoc/ice-reexport-crate-root-28927.rs index 38a520850b6dd..26debfc60e464 100644 --- a/tests/rustdoc/issue-28927.rs +++ b/tests/rustdoc/ice-reexport-crate-root-28927.rs @@ -2,5 +2,8 @@ // aux-build:issue-28927-1.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/28927 +#![crate_name="issue_28927"] + pub extern crate issue_28927_1 as inner1; pub use inner1 as foo; diff --git a/tests/rustdoc/issue-19181.rs b/tests/rustdoc/ice-type-error-19181.rs similarity index 68% rename from tests/rustdoc/issue-19181.rs rename to tests/rustdoc/ice-type-error-19181.rs index 3dea152fc6ecb..3ced613666406 100644 --- a/tests/rustdoc/issue-19181.rs +++ b/tests/rustdoc/ice-type-error-19181.rs @@ -1,4 +1,5 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/19181 // rustdoc should not panic when target crate has compilation errors diff --git a/tests/rustdoc/issue-21092.rs b/tests/rustdoc/impl-assoc-type-21092.rs similarity index 72% rename from tests/rustdoc/issue-21092.rs rename to tests/rustdoc/impl-assoc-type-21092.rs index b054145a4831a..f01f098a92f5d 100644 --- a/tests/rustdoc/issue-21092.rs +++ b/tests/rustdoc/impl-assoc-type-21092.rs @@ -1,6 +1,9 @@ // aux-build:issue-21092.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/21092 +#![crate_name="issue_21092"] + extern crate issue_21092; // @has issue_21092/struct.Bar.html diff --git a/tests/rustdoc/issue-20175.rs b/tests/rustdoc/impl-ref-20175.rs similarity index 68% rename from tests/rustdoc/issue-20175.rs rename to tests/rustdoc/impl-ref-20175.rs index 6a42e2afbf43c..a92db2d0a665b 100644 --- a/tests/rustdoc/issue-20175.rs +++ b/tests/rustdoc/impl-ref-20175.rs @@ -1,3 +1,7 @@ +// https://github.com/rust-lang/rust/issues/20175 + +#![crate_name="issue_20175"] + pub trait Foo { fn foo(&self) {} } diff --git a/tests/rustdoc/issue-16265-1.rs b/tests/rustdoc/infinite-redirection-16265-1.rs similarity index 71% rename from tests/rustdoc/issue-16265-1.rs rename to tests/rustdoc/infinite-redirection-16265-1.rs index 2fda637a64131..7d72469bd72c7 100644 --- a/tests/rustdoc/issue-16265-1.rs +++ b/tests/rustdoc/infinite-redirection-16265-1.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/16265 +#![crate_name="issue_16265_1"] + pub struct Foo; // @hasraw issue_16265_1/traits/index.html 'source' diff --git a/tests/rustdoc/issue-16265-2.rs b/tests/rustdoc/infinite-redirection-16265-2.rs similarity index 50% rename from tests/rustdoc/issue-16265-2.rs rename to tests/rustdoc/infinite-redirection-16265-2.rs index c3eb356171e85..7a4791c5fd487 100644 --- a/tests/rustdoc/issue-16265-2.rs +++ b/tests/rustdoc/infinite-redirection-16265-2.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/16265 +#![crate_name="issue_16265_2"] + // @hasraw issue_16265_2/index.html 'source' trait Y {} diff --git a/tests/rustdoc/issue-20727-2.rs b/tests/rustdoc/inline-assoc-type-20727-bindings.rs similarity index 90% rename from tests/rustdoc/issue-20727-2.rs rename to tests/rustdoc/inline-assoc-type-20727-bindings.rs index c1aa9617b2e25..e59dec29d030a 100644 --- a/tests/rustdoc/issue-20727-2.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bindings.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_2"] + extern crate issue_20727; // @has issue_20727_2/trait.Add.html diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs similarity index 90% rename from tests/rustdoc/issue-20727-3.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs index 2f9d91fc5f724..005ee3e329416 100644 --- a/tests/rustdoc/issue-20727-3.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_3"] + extern crate issue_20727; pub trait Bar {} diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/inline-assoc-type-20727-bounds-index.rs similarity index 95% rename from tests/rustdoc/issue-20727-4.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds-index.rs index ec9f18fc3feb8..1a3f4cd20c1e2 100644 --- a/tests/rustdoc/issue-20727-4.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds-index.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_4"] + extern crate issue_20727; // @has issue_20727_4/trait.Index.html diff --git a/tests/rustdoc/issue-20727.rs b/tests/rustdoc/inline-assoc-type-20727-bounds.rs similarity index 90% rename from tests/rustdoc/issue-20727.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds.rs index 266848beef93d..7cbc8d38107db 100644 --- a/tests/rustdoc/issue-20727.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727"] + extern crate issue_20727; // @has issue_20727/trait.Deref.html diff --git a/tests/rustdoc/inline_cross/async-fn.rs b/tests/rustdoc/inline_cross/async-fn.rs new file mode 100644 index 0000000000000..95e175aabd07d --- /dev/null +++ b/tests/rustdoc/inline_cross/async-fn.rs @@ -0,0 +1,19 @@ +// Regression test for issue #115760. +// Check that we render the correct return type of free and +// associated async functions reexported from external crates. + +// aux-crate:async_fn=async-fn.rs +// edition: 2021 +#![crate_name = "user"] + +// @has user/fn.load.html +// @has - '//pre[@class="rust item-decl"]' "pub async fn load() -> i32" +pub use async_fn::load; + +// @has user/trait.Load.html +// @has - '//*[@id="tymethod.run"]' 'async fn run(&self) -> i32' +pub use async_fn::Load; + +// @has user/struct.Loader.html +// @has - '//*[@id="method.run"]' 'async fn run(&self) -> i32' +pub use async_fn::Loader; diff --git a/tests/rustdoc/inline_cross/auxiliary/async-fn.rs b/tests/rustdoc/inline_cross/auxiliary/async-fn.rs new file mode 100644 index 0000000000000..767564ed145f3 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/async-fn.rs @@ -0,0 +1,18 @@ +#![feature(async_fn_in_trait)] +// edition: 2021 + +pub async fn load() -> i32 { + 0 +} + +pub trait Load { + async fn run(&self) -> i32; +} + +pub struct Loader; + +impl Load for Loader { + async fn run(&self) -> i32 { + 1 + } +} diff --git a/tests/rustdoc/inline_cross/auxiliary/fn-type.rs b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs new file mode 100644 index 0000000000000..dacda516bb88b --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs @@ -0,0 +1 @@ +pub type F = for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a (); diff --git a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 19433c9682bb0..fa61312ebc872 100644 --- a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -15,7 +15,7 @@ pub fn func4>(_x: T) {} pub fn func5( _f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>, - _a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>, + _a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>, ) {} pub trait Other { @@ -33,9 +33,3 @@ pub struct Foo; impl Foo { pub fn method<'a>(_x: impl Clone + Into> + 'a) {} } - -pub struct Bar; - -impl Bar { - pub async fn async_foo(&self) {} -} diff --git a/tests/rustdoc/auxiliary/issue-21801.rs b/tests/rustdoc/inline_cross/auxiliary/issue-21801.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-21801.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-21801.rs diff --git a/tests/rustdoc/auxiliary/issue-23207-1.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-23207-1.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs diff --git a/tests/rustdoc/auxiliary/issue-23207-2.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-23207-2.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs diff --git a/tests/rustdoc/auxiliary/issue-27362-aux.rs b/tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-27362-aux.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs diff --git a/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs new file mode 100644 index 0000000000000..9170be16892b9 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs @@ -0,0 +1,10 @@ +#![feature(non_lifetime_binders)] + +pub trait Trait {} + +pub fn f(_: impl for Trait) {} + +pub fn g(_: T) +where + T: for Trait, +{} diff --git a/tests/rustdoc/issue-27362.rs b/tests/rustdoc/inline_cross/const-fn-27362.rs similarity index 81% rename from tests/rustdoc/issue-27362.rs rename to tests/rustdoc/inline_cross/const-fn-27362.rs index 097e4e3b03d9d..39b904662e065 100644 --- a/tests/rustdoc/issue-27362.rs +++ b/tests/rustdoc/inline_cross/const-fn-27362.rs @@ -1,6 +1,9 @@ // aux-build:issue-27362-aux.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/27362 +#![crate_name="issue_27362"] + extern crate issue_27362_aux; pub use issue_27362_aux::*; diff --git a/tests/rustdoc/issue-23207.rs b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs similarity index 72% rename from tests/rustdoc/issue-23207.rs rename to tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs index 1a4b849ee8209..4e9596db589e2 100644 --- a/tests/rustdoc/issue-23207.rs +++ b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs @@ -2,6 +2,9 @@ // aux-build:issue-23207-2.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/23207 +#![crate_name="issue_23207"] + extern crate issue_23207_2; // @has issue_23207/fmt/index.html diff --git a/tests/rustdoc/inline_cross/fn-type.rs b/tests/rustdoc/inline_cross/fn-type.rs new file mode 100644 index 0000000000000..e65790d3b05aa --- /dev/null +++ b/tests/rustdoc/inline_cross/fn-type.rs @@ -0,0 +1,12 @@ +// Make sure that we print the higher-ranked parameters of cross-crate function pointer types. +// They should be rendered exactly as the user wrote it, i.e., in source order and with unused +// parameters present, not stripped. + +// aux-crate:fn_type=fn-type.rs +// edition: 2021 +#![crate_name = "user"] + +// @has user/type.F.html +// @has - '//*[@class="rust item-decl"]//code' \ +// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();" +pub use fn_type::F; diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs index b6a1552bc00ca..9b22026e49064 100644 --- a/tests/rustdoc/inline_cross/impl_trait.rs +++ b/tests/rustdoc/inline_cross/impl_trait.rs @@ -29,19 +29,11 @@ pub use impl_trait_aux::func4; // @has impl_trait/fn.func5.html // @has - '//pre[@class="rust item-decl"]' "func5(" // @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>," -// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>" +// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>" // @!has - '//pre[@class="rust item-decl"]' 'where' pub use impl_trait_aux::func5; -// @has impl_trait/fn.async_fn.html -// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()" -pub use impl_trait_aux::async_fn; - // @has impl_trait/struct.Foo.html // @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where' pub use impl_trait_aux::Foo; - -// @has impl_trait/struct.Bar.html -// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo(" -pub use impl_trait_aux::Bar; diff --git a/tests/rustdoc/inline_cross/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/non_lifetime_binders.rs new file mode 100644 index 0000000000000..9d3085c3ef264 --- /dev/null +++ b/tests/rustdoc/inline_cross/non_lifetime_binders.rs @@ -0,0 +1,13 @@ +// aux-crate:non_lifetime_binders=non_lifetime_binders.rs +// edition: 2021 +#![crate_name = "user"] + +// @has user/fn.f.html +// @has - '//pre[@class="rust item-decl"]' "f(_: impl for Trait)" +pub use non_lifetime_binders::f; + +// @has user/fn.g.html +// @has - '//pre[@class="rust item-decl"]' "g(_: T)\ +// where \ +// T: for Trait" +pub use non_lifetime_binders::g; diff --git a/tests/rustdoc/issue-21801.rs b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs similarity index 74% rename from tests/rustdoc/issue-21801.rs rename to tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs index 29d2ec64c206d..bcbb2e9f4088e 100644 --- a/tests/rustdoc/issue-21801.rs +++ b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs @@ -1,6 +1,9 @@ // aux-build:issue-21801.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/21801 +#![crate_name="issue_21801"] + extern crate issue_21801; // @has issue_21801/struct.Foo.html diff --git a/tests/rustdoc/issue-23106.rs b/tests/rustdoc/issue-23106.rs deleted file mode 100644 index 8cda2fc33805d..0000000000000 --- a/tests/rustdoc/issue-23106.rs +++ /dev/null @@ -1,7 +0,0 @@ -// compile-flags:--test - -/// ``` -/// # -/// ``` -pub fn main() { -} diff --git a/tests/rustdoc/issue-23812.rs b/tests/rustdoc/macro-doc-comment-23812.rs similarity index 89% rename from tests/rustdoc/issue-23812.rs rename to tests/rustdoc/macro-doc-comment-23812.rs index 08fd1833bcef3..57c18510b1e05 100644 --- a/tests/rustdoc/issue-23812.rs +++ b/tests/rustdoc/macro-doc-comment-23812.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/23812 +#![crate_name="issue_23812"] + macro_rules! doc { (#[$outer:meta] mod $i:ident { #![$inner:meta] }) => ( diff --git a/tests/rustdoc/issue-16019.rs b/tests/rustdoc/macro-ice-16019.rs similarity index 75% rename from tests/rustdoc/issue-16019.rs rename to tests/rustdoc/macro-ice-16019.rs index 239d92378d9bb..d0f82e0a314ce 100644 --- a/tests/rustdoc/issue-16019.rs +++ b/tests/rustdoc/macro-ice-16019.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/16019 + macro_rules! define_struct { ($rounds:expr) => ( struct Struct { diff --git a/tests/rustdoc/issue-27862.rs b/tests/rustdoc/markdown-table-escape-pipe-27862.rs similarity index 63% rename from tests/rustdoc/issue-27862.rs rename to tests/rustdoc/markdown-table-escape-pipe-27862.rs index 77522f1be2307..9af75d248884a 100644 --- a/tests/rustdoc/issue-27862.rs +++ b/tests/rustdoc/markdown-table-escape-pipe-27862.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/27862 +#![crate_name="issue_27862"] + /// Tests | Table /// ------|------------- /// t = b | id = \|x\| x diff --git a/tests/rustdoc/issue-17476.rs b/tests/rustdoc/method-link-foreign-trait-impl-17476.rs similarity index 76% rename from tests/rustdoc/issue-17476.rs rename to tests/rustdoc/method-link-foreign-trait-impl-17476.rs index a5b484c985fff..e52ab6f38c2a5 100644 --- a/tests/rustdoc/issue-17476.rs +++ b/tests/rustdoc/method-link-foreign-trait-impl-17476.rs @@ -1,5 +1,8 @@ // aux-build:issue-17476.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/17476 + +#![crate_name="issue_17476"] extern crate issue_17476; diff --git a/tests/rustdoc/no-crate-filter.rs b/tests/rustdoc/no-crate-filter.rs deleted file mode 100644 index b2f89906480d6..0000000000000 --- a/tests/rustdoc/no-crate-filter.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![crate_name = "foo"] - -// compile-flags: -Z unstable-options --disable-per-crate-search - -// @!has 'foo/struct.Foo.html' '//*[id="crate-search"]' '' -pub struct Foo; diff --git a/tests/rustdoc/issue-15318-3.rs b/tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs similarity index 61% rename from tests/rustdoc/issue-15318-3.rs rename to tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs index 2dab8f9488391..80c559756870c 100644 --- a/tests/rustdoc/issue-15318-3.rs +++ b/tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/15318 +#![crate_name="issue_15318_3"] #![feature(rustc_attrs)] // @has issue_15318_3/primitive.pointer.html diff --git a/tests/rustdoc/issue-15318.rs b/tests/rustdoc/primitive-raw-pointer-link-15318.rs similarity index 76% rename from tests/rustdoc/issue-15318.rs rename to tests/rustdoc/primitive-raw-pointer-link-15318.rs index 0349fe2854c8a..77f25ff4cff08 100644 --- a/tests/rustdoc/issue-15318.rs +++ b/tests/rustdoc/primitive-raw-pointer-link-15318.rs @@ -1,6 +1,8 @@ // aux-build:issue-15318.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/15318 +#![crate_name="issue_15318"] #![no_std] extern crate issue_15318; diff --git a/tests/rustdoc/issue-15318-2.rs b/tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs similarity index 75% rename from tests/rustdoc/issue-15318-2.rs rename to tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs index 614f2c1c08e87..1b35bb185ed48 100644 --- a/tests/rustdoc/issue-15318-2.rs +++ b/tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs @@ -1,5 +1,8 @@ // aux-build:issue-15318.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/15318 + +#![crate_name="issue_15318_2"] #![no_std] extern crate issue_15318; diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs index 5d742dc391a53..7f56b2ffeb8ad 100644 --- a/tests/rustdoc/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs @@ -5,6 +5,8 @@ // To future blessers: make sure that `const_trait_impl` is // stabilized when changing `@!has` to `@has`, and please do // not remove this test. +// +// FIXME(effects) add `const_trait` to `Fn` so we use `~const` #![feature(const_trait_impl)] #![crate_name = "foo"] @@ -22,9 +24,9 @@ pub trait Tr { // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' - fn a() + fn a() where - Option: ~const Fn() + ~const Destruct, + Option: /* ~const */ Fn() + ~const Destruct, { } } @@ -34,13 +36,13 @@ pub trait Tr { // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' -impl const Tr for T +impl const Tr for T where - Option: ~const Fn() + ~const Destruct, + Option: /* ~const */ Fn() + ~const Destruct, { - fn a() + fn a() where - Option: ~const Fn() + ~const Destruct, + Option: /* ~const */ Fn() + ~const Destruct, { } } @@ -49,9 +51,9 @@ where // @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' // @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const' // @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Fn' -pub const fn foo() +pub const fn foo() where - Option: ~const Fn() + ~const Destruct, + Option: /* ~const */ Fn() + ~const Destruct, { F::a() } @@ -61,9 +63,9 @@ impl S { // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' - pub const fn foo() + pub const fn foo() where - B: ~const Fn() + ~const Destruct, + B: /* ~const */ Fn() + ~const Destruct, { B::a() } diff --git a/tests/rustdoc/issue-23511.rs b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs similarity index 75% rename from tests/rustdoc/issue-23511.rs rename to tests/rustdoc/search-index-primitive-inherent-method-23511.rs index 21d02842431d0..1d0fe27e19273 100644 --- a/tests/rustdoc/issue-23511.rs +++ b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs @@ -2,6 +2,9 @@ #![feature(rustdoc_internals)] #![no_std] +// https://github.com/rust-lang/rust/issues/23511 +#![crate_name="issue_23511"] + pub mod str { #![rustc_doc_primitive = "str"] diff --git a/tests/rustdoc/issue-26606.rs b/tests/rustdoc/src-link-external-macro-26606.rs similarity index 56% rename from tests/rustdoc/issue-26606.rs rename to tests/rustdoc/src-link-external-macro-26606.rs index d5cb2c710cde8..de717a5273bb9 100644 --- a/tests/rustdoc/issue-26606.rs +++ b/tests/rustdoc/src-link-external-macro-26606.rs @@ -2,10 +2,13 @@ // ignore-cross-compile // build-aux-docs +// https://github.com/rust-lang/rust/issues/26606 +#![crate_name="issue_26606"] + // @has issue_26606_macro/macro.make_item.html #[macro_use] extern crate issue_26606_macro; // @has issue_26606/constant.FOO.html -// @has - '//a[@href="../src/issue_26606/issue-26606.rs.html#11"]' 'source' +// @has - '//a[@href="../src/issue_26606/src-link-external-macro-26606.rs.html#14"]' 'source' make_item!(FOO); diff --git a/tests/rustdoc/issue-26995.rs b/tests/rustdoc/src-mod-path-absolute-26995.rs similarity index 72% rename from tests/rustdoc/issue-26995.rs rename to tests/rustdoc/src-mod-path-absolute-26995.rs index fedc9f5174920..b67fd9b26db4b 100644 --- a/tests/rustdoc/issue-26995.rs +++ b/tests/rustdoc/src-mod-path-absolute-26995.rs @@ -1,6 +1,9 @@ // ignore-windows // compile-flags: --no-defaults +// https://github.com/rust-lang/rust/issues/26995 +#![crate_name="issue_26995"] + // @has src/issue_26995/dev/null.html // @has issue_26995/null/index.html '//a/@href' '../../src/issue_26995/dev/null.html' #[path="/dev/null"] diff --git a/tests/rustdoc/issue-27759.rs b/tests/rustdoc/staged-api-feature-issue-27759.rs similarity index 86% rename from tests/rustdoc/issue-27759.rs rename to tests/rustdoc/staged-api-feature-issue-27759.rs index 65e0f7cb87b0c..56a45a600da61 100644 --- a/tests/rustdoc/issue-27759.rs +++ b/tests/rustdoc/staged-api-feature-issue-27759.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/27759 +#![crate_name="issue_27759"] + #![feature(staged_api)] #![doc(issue_tracker_base_url = "http://issue_url/")] diff --git a/tests/rustdoc/issue-27104.rs b/tests/rustdoc/strip-priv-imports-pass-27104.rs similarity index 77% rename from tests/rustdoc/issue-27104.rs rename to tests/rustdoc/strip-priv-imports-pass-27104.rs index 9f2fd9071144f..e400a8f501181 100644 --- a/tests/rustdoc/issue-27104.rs +++ b/tests/rustdoc/strip-priv-imports-pass-27104.rs @@ -2,6 +2,9 @@ // aux-build:empty.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/27104 +#![crate_name="issue_27104"] + // @has issue_27104/index.html // @!hasraw - 'extern crate std' // @!hasraw - 'use std::prelude::' diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs index f6f0c038536c8..fa6734b6c6c30 100644 --- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs +++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -6,7 +6,7 @@ extern crate rustc_middle; extern crate rustc_session; -use rustc_session::lint::{LintArray, LintPass}; +use rustc_session::lint::{LintPass, LintVec}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; declare_lint! { diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs index bf655510a5ad8..3f7429a5fccf8 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -31,7 +31,6 @@ fn main() { TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Generator(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::` - TyKind::GeneratorWitnessMIR(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Never => (), //~ ERROR usage of `ty::TyKind::` TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Alias(..) => (), //~ ERROR usage of `ty::TyKind::` diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index 9f8c0bea0eeff..1f49d6b64646f 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -121,65 +121,59 @@ LL | TyKind::GeneratorWitness(..) => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:34:9 | -LL | TyKind::GeneratorWitnessMIR(..) => (), - | ^^^^^^ help: try using `ty::` directly: `ty` - -error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:35:9 - | LL | TyKind::Never => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:36:9 + --> $DIR/ty_tykind_usage.rs:35:9 | LL | TyKind::Tuple(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:37:9 + --> $DIR/ty_tykind_usage.rs:36:9 | LL | TyKind::Alias(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:38:9 + --> $DIR/ty_tykind_usage.rs:37:9 | LL | TyKind::Param(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:39:9 + --> $DIR/ty_tykind_usage.rs:38:9 | LL | TyKind::Bound(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:40:9 + --> $DIR/ty_tykind_usage.rs:39:9 | LL | TyKind::Placeholder(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:41:9 + --> $DIR/ty_tykind_usage.rs:40:9 | LL | TyKind::Infer(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:42:9 + --> $DIR/ty_tykind_usage.rs:41:9 | LL | TyKind::Error(_) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:47:12 + --> $DIR/ty_tykind_usage.rs:46:12 | LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:49:24 + --> $DIR/ty_tykind_usage.rs:48:24 | LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} | ^^^^^^^^^^ @@ -187,7 +181,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:51:37 + --> $DIR/ty_tykind_usage.rs:50:37 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -195,7 +189,7 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:51:53 + --> $DIR/ty_tykind_usage.rs:50:53 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -203,12 +197,12 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:54:9 + --> $DIR/ty_tykind_usage.rs:53:9 | LL | IrTyKind::Bool | --------^^^^^^ | | | help: try using `ty::` directly: `ty` -error: aborting due to 33 previous errors +error: aborting due to 32 previous errors diff --git a/tests/ui-fulldeps/lint-pass-macros.rs b/tests/ui-fulldeps/lint-pass-macros.rs index b3c2a542792f0..4c61783418fb0 100644 --- a/tests/ui-fulldeps/lint-pass-macros.rs +++ b/tests/ui-fulldeps/lint-pass-macros.rs @@ -5,7 +5,7 @@ extern crate rustc_session; -use rustc_session::lint::{LintArray, LintPass}; +use rustc_session::lint::{LintPass, LintVec}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; declare_lint! { diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs index 4a41e7fbb72a1..150f0c6b9a2da 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs @@ -5,13 +5,12 @@ // Load rustc as a plugin to get macros. extern crate rustc_driver; extern crate rustc_hir; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; use rustc_driver::plugin::Registry; -use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintId, LintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext, LintId}; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs index 30956deb799ed..acc5fe76051b9 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs @@ -6,14 +6,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; +use rustc_ast::ast; use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc_ast as ast; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs index c2c024865e8a8..21de4aa7008fd 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs @@ -4,14 +4,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintId, LintPass}; use rustc_ast as ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext, LintId}; + declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); declare_tool_lint!( /// Some docs diff --git a/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr index ae34b25cc2f80..66ea2e88f0c57 100644 --- a/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr +++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr @@ -27,6 +27,8 @@ LL | #![forbid(test_lint)] ... LL | #[allow(test_lint)] | ^^^^^^^^^ overruled by previous forbid + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-forbid-attrs.rs:5:1 diff --git a/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr index 491c4d2064681..9dbad702545cd 100644 --- a/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr +++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr @@ -21,6 +21,7 @@ LL | #[allow(test_lint)] | ^^^^^^^^^ overruled by previous forbid | = note: `forbid` lint level was set on command line + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-forbid-cmdline.rs:6:1 diff --git a/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr index 0e66179599989..4916b180a3670 100644 --- a/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr +++ b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr @@ -8,6 +8,7 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f | = help: change it to clippy::test_lint = note: requested on the command line with `-A test_lint` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: item is named 'lintme' --> $DIR/lint-tool-cmdline-allow.rs:9:1 @@ -29,6 +30,7 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f | = help: change it to clippy::test_lint = note: requested on the command line with `-A test_lint` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 5 warnings emitted diff --git a/tests/ui-fulldeps/plugin/lint-tool-test.stderr b/tests/ui-fulldeps/plugin/lint-tool-test.stderr index 027cf8f80cff2..d1f0714f04239 100644 --- a/tests/ui-fulldeps/plugin/lint-tool-test.stderr +++ b/tests/ui-fulldeps/plugin/lint-tool-test.stderr @@ -23,12 +23,16 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f | LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. --> $DIR/lint-tool-test.rs:13:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: item is named 'lintme' --> $DIR/lint-tool-test.rs:18:1 @@ -56,6 +60,8 @@ warning: lint name `test_group` is deprecated and may not have an effect in the | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `this_lint_does_not_exist` --> $DIR/lint-tool-test.rs:33:8 @@ -78,18 +84,24 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f | LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. --> $DIR/lint-tool-test.rs:13:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint name `test_group` is deprecated and may not have an effect in the future. --> $DIR/lint-tool-test.rs:29:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors; 11 warnings emitted diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index 642b58b0753fd..283d87d3eb604 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -1,7 +1,7 @@ // check-fail // Tests that a doc comment will not preclude a field from being considered a diagnostic argument // normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" -// normalize-stderr-test "diagnostic_builder\.rs:[0-9]+:[0-9]+" -> "diagnostic_builder.rs:LL:CC" +// normalize-stderr-test "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC" // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, // changing the output of this test. Since Subdiagnostic is strictly internal to the compiler diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index e014fc8c693ae..70d7b3225b599 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -23,7 +23,7 @@ LL | arg: NotIntoDiagnosticArg, | = help: normalized in stderr note: required by a bound in `Diagnostic::set_arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:968:5 + --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC error: aborting due to 2 previous errors diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index ca09f1f0153f2..014cd5a73bd8b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -414,6 +414,8 @@ error: `#[lint(...)]` is not a valid attribute | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:601:1 diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index 23a9e2a064cb6..3ec1519fb13c4 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -11,9 +11,10 @@ extern crate rustc_middle; extern crate rustc_smir; +extern crate stable_mir; use rustc_middle::ty::TyCtxt; -use rustc_smir::{rustc_internal, stable_mir}; +use rustc_smir::rustc_internal; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index a11720c4b5542..4aa14aea650b8 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -13,13 +13,13 @@ extern crate rustc_hir; extern crate rustc_middle; extern crate rustc_smir; +extern crate stable_mir; use rustc_hir::def::DefKind; use rustc_middle::ty::TyCtxt; -use rustc_smir::{ - rustc_internal, - stable_mir::{self, fold::Foldable}, -}; +use rustc_smir::rustc_internal; + +use stable_mir::fold::Foldable; use std::assert_matches::assert_matches; use std::io::Write; use std::ops::ControlFlow; @@ -27,7 +27,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { // Get the local crate using stable_mir API. let local = stable_mir::local_crate(); assert_eq!(&local.name, CRATE_NAME); @@ -36,88 +36,88 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); - assert!(get_item(tcx, &items, (DefKind::Fn, "foo::bar")).is_some()); + assert!(get_item(&items, (DefKind::Fn, "foo::bar")).is_some()); - // Find the `std` crate. - assert!(stable_mir::find_crate("std").is_some()); + // Find the `std` crate and assert that there is only one of it. + assert!(stable_mir::find_crates("std").len() == 1); - let bar = get_item(tcx, &items, (DefKind::Fn, "bar")).unwrap(); + let bar = get_item(&items, (DefKind::Fn, "bar")).unwrap(); let body = bar.body(); assert_eq!(body.locals.len(), 2); assert_eq!(body.blocks.len(), 1); let block = &body.blocks[0]; assert_eq!(block.statements.len(), 1); - match &block.statements[0] { - stable_mir::mir::Statement::Assign(..) => {} + match &block.statements[0].kind { + stable_mir::mir::StatementKind::Assign(..) => {} other => panic!("{other:?}"), } - match &block.terminator { - stable_mir::mir::Terminator::Return => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Return => {} other => panic!("{other:?}"), } - let foo_bar = get_item(tcx, &items, (DefKind::Fn, "foo_bar")).unwrap(); + let foo_bar = get_item(&items, (DefKind::Fn, "foo_bar")).unwrap(); let body = foo_bar.body(); assert_eq!(body.locals.len(), 7); assert_eq!(body.blocks.len(), 4); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Call { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Call { .. } => {} other => panic!("{other:?}"), } - let types = get_item(tcx, &items, (DefKind::Fn, "types")).unwrap(); + let types = get_item(&items, (DefKind::Fn, "types")).unwrap(); let body = types.body(); assert_eq!(body.locals.len(), 6); assert_matches!( - body.locals[0].kind(), + body.locals[0].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) ); assert_matches!( - body.locals[1].kind(), + body.locals[1].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) ); assert_matches!( - body.locals[2].kind(), + body.locals[2].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Char) ); assert_matches!( - body.locals[3].kind(), + body.locals[3].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Int(stable_mir::ty::IntTy::I32)) ); assert_matches!( - body.locals[4].kind(), + body.locals[4].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Uint(stable_mir::ty::UintTy::U64)) ); assert_matches!( - body.locals[5].kind(), + body.locals[5].ty.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 drop = get_item(&items, (DefKind::Fn, "drop")).unwrap(); let body = drop.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Drop { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Drop { .. } => {} other => panic!("{other:?}"), } - let assert = get_item(tcx, &items, (DefKind::Fn, "assert")).unwrap(); + let assert = get_item(&items, (DefKind::Fn, "assert")).unwrap(); let body = assert.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Assert { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Assert { .. } => {} other => panic!("{other:?}"), } - let monomorphic = get_item(tcx, &items, (DefKind::Fn, "monomorphic")).unwrap(); + let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap(); for block in monomorphic.body().blocks { - match &block.terminator { - stable_mir::mir::Terminator::Call { func, .. } => match func { + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Call { func, .. } => match func { stable_mir::mir::Operand::Constant(c) => match &c.literal.literal { stable_mir::ty::ConstantKind::Allocated(alloc) => { assert!(alloc.bytes.is_empty()); @@ -127,7 +127,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { mut args, )) => { let func = def.body(); - match func.locals[1] + match func.locals[1].ty .fold(&mut args) .continue_value() .unwrap() @@ -149,12 +149,12 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { }, other => panic!("{other:?}"), }, - stable_mir::mir::Terminator::Return => {} + stable_mir::mir::TerminatorKind::Return => {} other => panic!("{other:?}"), } } - let foo_const = get_item(tcx, &items, (DefKind::Const, "FOO")).unwrap(); + let foo_const = get_item(&items, (DefKind::Const, "FOO")).unwrap(); // Ensure we don't panic trying to get the body of a constant. foo_const.body(); @@ -163,13 +163,11 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { // Use internal API to find a function in a crate. fn get_item<'a>( - tcx: TyCtxt, items: &'a stable_mir::CrateItems, item: (DefKind, &str), ) -> Option<&'a stable_mir::CrateItem> { items.iter().find(|crate_item| { - let def_id = rustc_internal::item_def_id(crate_item); - tcx.def_kind(def_id) == item.0 && tcx.def_path_str(def_id) == item.1 + crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1 }) } diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 249e817628303..1f049b1785a62 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -1,16 +1,174 @@ // check-pass +// revisions: host +// revisions: arm +//[arm] compile-flags: --target arm-unknown-linux-gnueabi +//[arm] needs-llvm-components: arm +// revisions: aarch64 +//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//[aarch64] needs-llvm-components: aarch64 +// revisions: s390x +//[s390x] compile-flags: --target s390x-unknown-linux-gnu +//[s390x] needs-llvm-components: systemz +// revisions: mips +//[mips] compile-flags: --target mips-unknown-linux-gnu +//[mips] needs-llvm-components: mips +// revisions: mips64 +//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +//[mips64] needs-llvm-components: mips +// revisions: sparc +//[sparc] compile-flags: --target sparc-unknown-linux-gnu +//[sparc] needs-llvm-components: sparc +// revisions: sparc64 +//[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//[sparc64] needs-llvm-components: sparc +// revisions: powerpc64 +//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//[powerpc64] needs-llvm-components: powerpc +// revisions: riscv +//[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +//[riscv] needs-llvm-components: riscv +// revisions: loongarch64 +//[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//[loongarch64] needs-llvm-components: loongarch +// revisions: wasm +//[wasm] compile-flags: --target wasm32-unknown-unknown +//[wasm] needs-llvm-components: webassembly +// revisions: wasi +//[wasi] compile-flags: --target wasm32-wasi +//[wasi] needs-llvm-components: webassembly +// revisions: nvptx64 +//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda +//[nvptx64] needs-llvm-components: nvptx #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] +#![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)] #![allow(unused, improper_ctypes_definitions, internal_features)] -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::num::NonZeroI32; -use std::ptr::NonNull; -// FIXME: a bunch of targets are broken in various ways. +// FIXME: some targets are broken in various ways. // Hence there are `cfg` throughout this test to disable parts of it on those targets. // sparc64: https://github.com/rust-lang/rust/issues/115336 // mips64: https://github.com/rust-lang/rust/issues/115404 +#[cfg(host)] +use std::{ + any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZeroI32, ptr::NonNull, rc::Rc, + sync::Arc, +}; + +/// To work cross-target this test must be no_core. +/// This little prelude supplies what we need. +#[cfg(not(host))] +mod prelude { + #[lang = "sized"] + pub trait Sized {} + + #[lang = "receiver"] + pub trait Receiver {} + impl Receiver for &T {} + impl Receiver for &mut T {} + + #[lang = "copy"] + pub trait Copy: Sized {} + impl Copy for i32 {} + impl Copy for f32 {} + impl Copy for &T {} + impl Copy for *const T {} + impl Copy for *mut T {} + + #[lang = "clone"] + pub trait Clone: Sized { + fn clone(&self) -> Self; + } + + #[lang = "phantom_data"] + pub struct PhantomData; + impl Copy for PhantomData {} + + #[lang = "unsafe_cell"] + #[repr(transparent)] + pub struct UnsafeCell { + value: T, + } + + pub trait Any: 'static {} + + pub enum Option { + None, + Some(T), + } + impl Copy for Option {} + + pub enum Result { + Ok(T), + Err(E), + } + impl Copy for Result {} + + #[lang = "manually_drop"] + #[repr(transparent)] + pub struct ManuallyDrop { + value: T, + } + impl Copy for ManuallyDrop {} + + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + pub struct NonNull { + pointer: *const T, + } + impl Copy for NonNull {} + + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + pub struct NonZeroI32(i32); + + // This just stands in for a non-trivial type. + pub struct Vec { + ptr: NonNull, + cap: usize, + len: usize, + } + + pub struct Unique { + pub pointer: NonNull, + pub _marker: PhantomData, + } + + pub struct Global; + + #[lang = "owned_box"] + pub struct Box(Unique, A); + + #[repr(C)] + struct RcBox { + strong: UnsafeCell, + weak: UnsafeCell, + value: T, + } + pub struct Rc { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, + } + + #[repr(C, align(8))] + struct AtomicUsize(usize); + #[repr(C)] + struct ArcInner { + strong: AtomicUsize, + weak: AtomicUsize, + data: T, + } + pub struct Arc { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, + } +} +#[cfg(not(host))] +use prelude::*; + macro_rules! assert_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { mod $name { @@ -26,8 +184,13 @@ macro_rules! assert_abi_compatible { }; } -#[derive(Copy, Clone)] struct Zst; +impl Copy for Zst {} +impl Clone for Zst { + fn clone(&self) -> Self { + Zst + } +} #[repr(C)] struct ReprC1(T); @@ -85,8 +248,8 @@ test_abi_compatible!(nonzero_int, NonZeroI32, i32); // `DispatchFromDyn` relies on ABI compatibility. // This is interesting since these types are not `repr(transparent)`. -test_abi_compatible!(rc, std::rc::Rc, *mut i32); -test_abi_compatible!(arc, std::sync::Arc, *mut i32); +test_abi_compatible!(rc, Rc, *mut i32); +test_abi_compatible!(arc, Arc, *mut i32); // `repr(transparent)` compatibility. #[repr(transparent)] @@ -160,7 +323,7 @@ mod unsized_ { use super::*; test_transparent_unsized!(str_, str); test_transparent_unsized!(slice, [u8]); - test_transparent_unsized!(dyn_trait, dyn std::any::Any); + test_transparent_unsized!(dyn_trait, dyn Any); } // RFC 3391 . @@ -185,7 +348,7 @@ test_nonnull!(ref_unsized, &[i32]); test_nonnull!(mut_unsized, &mut [i32]); test_nonnull!(fn_, fn()); test_nonnull!(nonnull, NonNull); -test_nonnull!(nonnull_unsized, NonNull); +test_nonnull!(nonnull_unsized, NonNull); test_nonnull!(non_zero, NonZeroI32); fn main() {} diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs index 0cfc44cd09d80..cca2e8db74d75 100644 --- a/tests/ui/abi/relocation_model_pic.rs +++ b/tests/ui/abi/relocation_model_pic.rs @@ -1,7 +1,6 @@ // run-pass // compile-flags: -C relocation-model=pic -// ignore-emscripten no pic -// ignore-wasm +// needs-relocation-model-pic #![feature(cfg_relocation_model)] diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr index 62bb0679f813a..e1967b700133e 100644 --- a/tests/ui/allocator/not-an-allocator.stderr +++ b/tests/ui/allocator/not-an-allocator.stderr @@ -18,6 +18,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = help: the trait `GlobalAlloc` is implemented for `System` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -29,6 +30,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = help: the trait `GlobalAlloc` is implemented for `System` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -40,6 +42,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = help: the trait `GlobalAlloc` is implemented for `System` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr index d2ea08aa47430..619417a73c9ee 100644 --- a/tests/ui/array-slice-vec/vector-no-ann.stderr +++ b/tests/ui/array-slice-vec/vector-no-ann.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec` --> $DIR/vector-no-ann.rs:2:9 | LL | let _foo = Vec::new(); - | ^^^^ + | ^^^^ ---------- type must be known at this point | help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified | diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index 875df44ffab78..d647f6a9f0635 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -22,7 +22,7 @@ LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:36]` for inline assembly +error: cannot use value of type `{closure@$DIR/type-check-2.rs:41:28: 41:36}` for inline assembly --> $DIR/type-check-2.rs:41:28 | LL | asm!("{}", in(reg) |x: i32| x); diff --git a/tests/ui/asm/x86_64/issue-96797.rs b/tests/ui/asm/x86_64/issue-96797.rs index 951dd949b3251..6c22c2f6c9463 100644 --- a/tests/ui/asm/x86_64/issue-96797.rs +++ b/tests/ui/asm/x86_64/issue-96797.rs @@ -11,7 +11,14 @@ use std::arch::global_asm; #[no_mangle] fn my_func() {} -global_asm!("call_foobar: jmp {}", sym foobar); +global_asm!(" +.globl call_foobar +.type call_foobar,@function +.pushsection .text.call_foobar,\"ax\",@progbits +call_foobar: jmp {} +.size call_foobar, .-call_foobar +.popsection +", sym foobar); fn foobar() {} diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index d9ca25519dc8a..4f3d5100af056 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -30,7 +30,7 @@ LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:36]` for inline assembly +error: cannot use value of type `{closure@$DIR/type-check-2.rs:52:28: 52:36}` for inline assembly --> $DIR/type-check-2.rs:52:28 | LL | asm!("{}", in(reg) |x: i32| x); diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr index d659912341aaf..ac5ec8e05ea96 100644 --- a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -24,6 +24,7 @@ note: erroneous constant encountered LL | assert_eq!(<() as Tr>::B, 0); // causes the error above | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 927422fa8dcaf..200856caa2518 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -33,7 +33,7 @@ LL | fn main>() { = note: see issue #92827 for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/issue-105330.rs:6:27 | LL | impl TraitWAssocConst for impl Demo { diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr index 84fc85cd09e48..e844f6795e6f8 100644 --- a/tests/ui/associated-inherent-types/issue-109789.stderr +++ b/tests/ui/associated-inherent-types/issue-109789.stderr @@ -15,6 +15,7 @@ LL | fn bar(_: Foo fn(&'a ())>::Assoc) {} | = note: expected struct `Foo` found struct `Foo fn(&'a ())>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr index 689b45e09aaac..bf35f2bb5b532 100644 --- a/tests/ui/associated-inherent-types/issue-111879-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr @@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type LL | fn main(_: for<'a> fn(Foo::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn()` - found fn pointer `fn(for<'a> fn(Foo::Assoc))` + = note: expected signature `fn()` + found signature `fn(for<'a> fn(&'a ()))` error: aborting due to previous error diff --git a/tests/ui/associated-inherent-types/regionck-1.stderr b/tests/ui/associated-inherent-types/regionck-1.stderr index b17d89ca306f4..62a00868248a5 100644 --- a/tests/ui/associated-inherent-types/regionck-1.stderr +++ b/tests/ui/associated-inherent-types/regionck-1.stderr @@ -2,9 +2,14 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regionck-1.rs:9:30 | LL | type NoTyOutliv<'a, T> = &'a T; - | ^^^^^- help: consider adding a where clause: `where T: 'a` - | | - | ...so that the reference type `&'a T` does not outlive the data it points at + | -- ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | type NoTyOutliv<'a, T: 'a> = &'a T; + | ++++ error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references --> $DIR/regionck-1.rs:10:31 diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs index 5c59f217be6d2..9976969234234 100644 --- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs +++ b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs @@ -1,6 +1,5 @@ -// FIXME(inherent_associated_types): This should be `check-pass` -// known-bug: #108491 // compile-flags: --crate-type=lib +// check-pass #![feature(inherent_associated_types)] #![allow(incomplete_features)] @@ -8,11 +7,6 @@ // Bounds on the self type play a major role in the resolution of inherent associated types (*). // As a result of that, if a type alias contains any then its bounds have to be respected and the // lint `type_alias_bounds` should not fire. -// -// FIXME(inherent_associated_types): In the current implementation that is. We might move the -// selection phase of IATs from hir_typeck to trait_selection resulting in us not requiring the -// ParamEnv that early allowing us to ignore bounds on type aliases again. -// Triage this before stabilization. #![deny(type_alias_bounds)] diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr deleted file mode 100644 index 5e18543fc9001..0000000000000 --- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0391]: cycle detected when expanding type alias `Alias` - --> $DIR/type-alias-bounds-are-enforced.rs:19:1 - | -LL | pub type Alias = (Source::Assoc,); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing the variances of `Source`... - --> $DIR/type-alias-bounds-are-enforced.rs:21:1 - | -LL | pub struct Source(T); - | ^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing the variances for items in this crate... - = note: ...which again requires expanding type alias `Alias`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/type-alias-bounds-are-enforced.rs:5:1 - | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*). -... | -LL | | pub type Assoc = (); -LL | | } - | |_^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0391]: cycle detected when expanding type alias `Alias` - --> $DIR/type-alias-bounds-are-enforced.rs:19:1 - | -LL | pub type Alias = (Source::Assoc,); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing the variances of `Source`... - --> $DIR/type-alias-bounds-are-enforced.rs:21:1 - | -LL | pub struct Source(T); - | ^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing the variances for items in this crate... - = note: ...which again requires expanding type alias `Alias`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/type-alias-bounds-are-enforced.rs:5:1 - | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*). -... | -LL | | pub type Assoc = (); -LL | | } - | |_^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index 08721eff7b0ce..3629aa4fceac2 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -373,6 +373,8 @@ LL | trait TRS1: Iterator {} | ---------- ^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:197:34 @@ -389,6 +391,8 @@ LL | trait TRS2: Iterator {} | ---------- ^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:200:37 @@ -405,6 +409,8 @@ LL | trait TRS3: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:205:29 @@ -445,6 +451,8 @@ LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:230:32 @@ -461,6 +469,8 @@ LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:237:35 @@ -477,6 +487,8 @@ LL | Self: Iterator, | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:255:40 diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr index 15cc9646b2c8e..09c8ec2e289f5 100644 --- a/tests/ui/associated-type-bounds/issue-71443-1.stderr +++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-71443-1.rs:6:5 | LL | fn hello Iterator>() { - | - help: try adding a return type: `-> Incorrect` + | - help: try adding a return type: `-> Incorrect` LL | Incorrect | ^^^^^^^^^ expected `()`, found `Incorrect` diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr index 40c02dca32f0d..211613b371492 100644 --- a/tests/ui/associated-types/associated-types-coherence-failure.stderr +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -2,19 +2,19 @@ error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Co --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { - | ------------------------------------------------------------ first implementation here + | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { - | ------------------------------------------------------------ first implementation here + | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/defaults-specialization.stderr b/tests/ui/associated-types/defaults-specialization.stderr index 7e21f7fc306d2..7ef433d859fa4 100644 --- a/tests/ui/associated-types/defaults-specialization.stderr +++ b/tests/ui/associated-types/defaults-specialization.stderr @@ -29,7 +29,7 @@ error[E0053]: method `make` has an incompatible type for trait --> $DIR/defaults-specialization.rs:35:18 | LL | default type Ty = bool; - | ----------------------- expected this associated type + | ----------------------- associated type is `default` and may be overridden LL | LL | fn make() -> bool { true } | ^^^^ @@ -76,7 +76,7 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:44:29 | LL | default type Ty = bool; - | ----------------------- expected this associated type + | ----------------------- associated type is `default` and may be overridden LL | LL | fn make() -> Self::Ty { true } | -------- ^^^^ expected associated type, found `bool` diff --git a/tests/ui/associated-types/hr-associated-type-bound-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-2.stderr index 749986f09c63d..8ccbc9fb5144a 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-2.stderr @@ -1,8 +1,10 @@ error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` --> $DIR/hr-associated-type-bound-2.rs:11:1 | -LL | impl X<'_> for u32 - | ^^^^^^^^^^^^^^^^^^ +LL | / impl X<'_> for u32 +LL | | where +LL | | for<'b> >::U: Clone, + | |______________________________________^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`) note: required for `u32` to implement `for<'b> X<'b>` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr index 366670269d7cd..1a749007ab674 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -45,6 +45,7 @@ LL | trait Z<'a, T: ?Sized> ... LL | for<'b> >::W: Clone, | ^^^^^ required by this bound in `Z` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/impl-wf-cycle-1.stderr b/tests/ui/associated-types/impl-wf-cycle-1.stderr index 206060f1980db..53022dcb4c787 100644 --- a/tests/ui/associated-types/impl-wf-cycle-1.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-1.stderr @@ -1,8 +1,12 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` --> $DIR/impl-wf-cycle-1.rs:15:1 | -LL | impl Grault for (T,) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl Grault for (T,) +LL | | +LL | | where +LL | | Self::A: Baz, +LL | | Self::B: Fiz, + | |_________________^ | note: required for `(T,)` to implement `Grault` --> $DIR/impl-wf-cycle-1.rs:15:17 diff --git a/tests/ui/associated-types/impl-wf-cycle-2.stderr b/tests/ui/associated-types/impl-wf-cycle-2.stderr index 771ba751e8c95..81c58be927e6d 100644 --- a/tests/ui/associated-types/impl-wf-cycle-2.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-2.stderr @@ -1,8 +1,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` --> $DIR/impl-wf-cycle-2.rs:7:1 | -LL | impl Grault for (T,) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl Grault for (T,) +LL | | +LL | | where +LL | | Self::A: Copy, + | |__________________^ | note: required for `(T,)` to implement `Grault` --> $DIR/impl-wf-cycle-2.rs:7:17 diff --git a/tests/ui/async-await/async-await-let-else.drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.drop-tracking.stderr deleted file mode 100644 index fb83ca90a3787..0000000000000 --- a/tests/ui/async-await/async-await-let-else.drop-tracking.stderr +++ /dev/null @@ -1,106 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:48:13 - | -LL | is_send(foo(Some(true))); - | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:11:14 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await - | ^^^^^^ await occurs here, with `r` maybe used later -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error[E0277]: `Rc<()>` cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:50:13 - | -LL | async fn foo2(x: Option) { - | - within this `impl Future` -... -LL | is_send(foo2(Some(true))); - | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely - | | - | required by a bound introduced by this call - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:27:29 - | -LL | async fn bar2(_: T) -> ! { - | _____________________________^ -LL | | panic!() -LL | | } - | |_^ - = note: required because it captures the following types: `ResumeTy`, `Option`, `impl Future`, `()` -note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:21:32 - | -LL | async fn foo2(x: Option) { - | ________________________________^ -LL | | let Some(_) = x else { -LL | | bar2(Rc::new(())).await -LL | | }; -LL | | } - | |_^ -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:52:13 - | -LL | is_send(foo3(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:33:28 - | -LL | (Rc::new(()), bar().await); - | ----------- ^^^^^^ - `Rc::new(())` is later dropped here - | | | - | | await occurs here, with `Rc::new(())` maybe used later - | has type `Rc<()>` which is not `Send` -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:54:13 - | -LL | is_send(foo4(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:41:14 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await; - | ^^^^^^ await occurs here, with `r` maybe used later -... -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-await-let-else.drop_tracking.stderr b/tests/ui/async-await/async-await-let-else.drop_tracking.stderr deleted file mode 100644 index dee90262fd443..0000000000000 --- a/tests/ui/async-await/async-await-let-else.drop_tracking.stderr +++ /dev/null @@ -1,106 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:48:13 - | -LL | is_send(foo(Some(true))); - | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:11:15 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await - | ^^^^^ await occurs here, with `r` maybe used later -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error[E0277]: `Rc<()>` cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:50:13 - | -LL | async fn foo2(x: Option) { - | - within this `impl Future` -... -LL | is_send(foo2(Some(true))); - | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely - | | - | required by a bound introduced by this call - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:27:29 - | -LL | async fn bar2(_: T) -> ! { - | _____________________________^ -LL | | panic!() -LL | | } - | |_^ - = note: required because it captures the following types: `ResumeTy`, `Option`, `impl Future`, `()` -note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:21:32 - | -LL | async fn foo2(x: Option) { - | ________________________________^ -LL | | let Some(_) = x else { -LL | | bar2(Rc::new(())).await -LL | | }; -LL | | } - | |_^ -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:52:13 - | -LL | is_send(foo3(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:33:29 - | -LL | (Rc::new(()), bar().await); - | ----------- ^^^^^ - `Rc::new(())` is later dropped here - | | | - | | await occurs here, with `Rc::new(())` maybe used later - | has type `Rc<()>` which is not `Send` -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:54:13 - | -LL | is_send(foo4(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:41:15 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await; - | ^^^^^ await occurs here, with `r` maybe used later -... -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr deleted file mode 100644 index d3c5e80a30df4..0000000000000 --- a/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr +++ /dev/null @@ -1,90 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:48:13 - | -LL | is_send(foo(Some(true))); - | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:11:14 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await - | ^^^^^^ await occurs here, with `r` maybe used later -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:50:13 - | -LL | is_send(foo2(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:23:26 - | -LL | bar2(Rc::new(())).await - | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later - | | - | has type `Rc<()>` which is not `Send` -LL | }; - | - `Rc::new(())` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:52:13 - | -LL | is_send(foo3(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:33:28 - | -LL | (Rc::new(()), bar().await); - | ----------- ^^^^^^ - `Rc::new(())` is later dropped here - | | | - | | await occurs here, with `Rc::new(())` maybe used later - | has type `Rc<()>` which is not `Send` -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:54:13 - | -LL | is_send(foo4(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:41:14 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await; - | ^^^^^^ await occurs here, with `r` maybe used later -... -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr b/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr deleted file mode 100644 index ece4e51ecff10..0000000000000 --- a/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr +++ /dev/null @@ -1,90 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:48:13 - | -LL | is_send(foo(Some(true))); - | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:11:15 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await - | ^^^^^ await occurs here, with `r` maybe used later -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:50:13 - | -LL | is_send(foo2(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:23:27 - | -LL | bar2(Rc::new(())).await - | ----------- ^^^^^ await occurs here, with `Rc::new(())` maybe used later - | | - | has type `Rc<()>` which is not `Send` -LL | }; - | - `Rc::new(())` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:52:13 - | -LL | is_send(foo3(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:33:29 - | -LL | (Rc::new(()), bar().await); - | ----------- ^^^^^ - `Rc::new(())` is later dropped here - | | | - | | await occurs here, with `Rc::new(())` maybe used later - | has type `Rc<()>` which is not `Send` -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:54:13 - | -LL | is_send(foo4(Some(true))); - | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:41:15 - | -LL | let r = Rc::new(()); - | - has type `Rc<()>` which is not `Send` -LL | bar().await; - | ^^^^^ await occurs here, with `r` maybe used later -... -LL | }; - | - `r` is later dropped here -note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 - | -LL | fn is_send(_: T) {} - | ^^^^ required by this bound in `is_send` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/async-await-let-else.rs b/tests/ui/async-await/async-await-let-else.rs index 113d576b5e762..a3c7226056b29 100644 --- a/tests/ui/async-await/async-await-let-else.rs +++ b/tests/ui/async-await/async-await-let-else.rs @@ -1,7 +1,4 @@ // edition:2021 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir use std::rc::Rc; diff --git a/tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr b/tests/ui/async-await/async-await-let-else.stderr similarity index 83% rename from tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr rename to tests/ui/async-await/async-await-let-else.stderr index e3fcceaa3921a..c3b4e761824f8 100644 --- a/tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr +++ b/tests/ui/async-await/async-await-let-else.stderr @@ -1,28 +1,28 @@ error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:48:13 + --> $DIR/async-await-let-else.rs:45:13 | LL | is_send(foo(Some(true))); | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:11:15 + --> $DIR/async-await-let-else.rs:8:15 | LL | let r = Rc::new(()); | - has type `Rc<()>` which is not `Send` LL | bar().await | ^^^^^ await occurs here, with `r` maybe used later note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 + --> $DIR/async-await-let-else.rs:16:15 | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` error[E0277]: `Rc<()>` cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:50:13 + --> $DIR/async-await-let-else.rs:47:13 | LL | async fn foo2(x: Option) { - | - within this `impl Future` + | ------------------------------ within this `impl Future` ... LL | is_send(foo2(Some(true))); | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely @@ -31,7 +31,7 @@ LL | is_send(foo2(Some(true))); | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:27:29 + --> $DIR/async-await-let-else.rs:24:29 | LL | async fn bar2(_: T) -> ! { | _____________________________^ @@ -40,7 +40,7 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future` note: required because it's used within this `async fn` body - --> $DIR/async-await-let-else.rs:21:32 + --> $DIR/async-await-let-else.rs:18:32 | LL | async fn foo2(x: Option) { | ________________________________^ @@ -50,47 +50,47 @@ LL | | }; LL | | } | |_^ note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 + --> $DIR/async-await-let-else.rs:16:15 | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:52:13 + --> $DIR/async-await-let-else.rs:49:13 | LL | is_send(foo3(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:33:29 + --> $DIR/async-await-let-else.rs:30:29 | LL | (Rc::new(()), bar().await); | ----------- ^^^^^ await occurs here, with `Rc::new(())` maybe used later | | | has type `Rc<()>` which is not `Send` note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 + --> $DIR/async-await-let-else.rs:16:15 | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:54:13 + --> $DIR/async-await-let-else.rs:51:13 | LL | is_send(foo4(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:41:15 + --> $DIR/async-await-let-else.rs:38:15 | LL | let r = Rc::new(()); | - has type `Rc<()>` which is not `Send` LL | bar().await; | ^^^^^ await occurs here, with `r` maybe used later note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:19:15 + --> $DIR/async-await-let-else.rs:16:15 | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr index bbd5a822d8df5..c89671cc4811b 100644 --- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -29,13 +29,13 @@ LL | | LL | | } | |_^ expected `u8`, found `()` -error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to be a future that resolves to `()`, but it resolves to `u8` +error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to be a future that resolves to `()`, but it resolves to `u8` --> $DIR/async-block-control-flow-static-semantics.rs:26:39 | LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to `&dyn Future` + = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to `&dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:12:43 @@ -45,13 +45,13 @@ LL | fn return_targets_async_block_not_fn() -> u8 { | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to be a future that resolves to `()`, but it resolves to `u8` +error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to be a future that resolves to `()`, but it resolves to `u8` --> $DIR/async-block-control-flow-static-semantics.rs:17:39 | LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to `&dyn Future` + = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to `&dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:49:44 diff --git a/tests/ui/async-await/async-error-span.drop_tracking.stderr b/tests/ui/async-await/async-error-span.drop_tracking.stderr deleted file mode 100644 index 99a674a2684c4..0000000000000 --- a/tests/ui/async-await/async-error-span.drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: `()` is not a future - --> $DIR/async-error-span.rs:10:20 - | -LL | fn get_future() -> impl Future { - | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:16:9 - | -LL | let a; - | ^ cannot infer type - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:19:18 - | -LL | get_future().await; - | ^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0698. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-error-span.no_drop_tracking.stderr b/tests/ui/async-await/async-error-span.no_drop_tracking.stderr deleted file mode 100644 index 99a674a2684c4..0000000000000 --- a/tests/ui/async-await/async-error-span.no_drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: `()` is not a future - --> $DIR/async-error-span.rs:10:20 - | -LL | fn get_future() -> impl Future { - | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:16:9 - | -LL | let a; - | ^ cannot infer type - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:19:18 - | -LL | get_future().await; - | ^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0698. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-error-span.rs b/tests/ui/async-await/async-error-span.rs index c9ecf359e3de5..c8127df625e68 100644 --- a/tests/ui/async-await/async-error-span.rs +++ b/tests/ui/async-await/async-error-span.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 // Regression test for issue #62382. @@ -13,9 +10,7 @@ fn get_future() -> impl Future { } async fn foo() { - let a; - //[no_drop_tracking,drop_tracking]~^ ERROR type inside `async fn` body must be known in this context - //[drop_tracking_mir]~^^ ERROR type annotations needed + let a; //~ ERROR type annotations needed get_future().await; } diff --git a/tests/ui/async-await/async-error-span.drop_tracking_mir.stderr b/tests/ui/async-await/async-error-span.stderr similarity index 89% rename from tests/ui/async-await/async-error-span.drop_tracking_mir.stderr rename to tests/ui/async-await/async-error-span.stderr index 2f29ee6cdb0a1..2ec968ffc0307 100644 --- a/tests/ui/async-await/async-error-span.drop_tracking_mir.stderr +++ b/tests/ui/async-await/async-error-span.stderr @@ -1,5 +1,5 @@ error[E0277]: `()` is not a future - --> $DIR/async-error-span.rs:10:20 + --> $DIR/async-error-span.rs:7:20 | LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future @@ -8,7 +8,7 @@ LL | fn get_future() -> impl Future { = note: () must be a future or must implement `IntoFuture` to be awaited error[E0282]: type annotations needed - --> $DIR/async-error-span.rs:16:9 + --> $DIR/async-error-span.rs:13:9 | LL | let a; | ^ diff --git a/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr b/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr deleted file mode 100644 index 0515edaeda342..0000000000000 --- a/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:72:17 - | -LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:36:26 - | -LL | match Some(non_send()) { - | ---------------- has type `Option` which is not `Send` -LL | Some(_) => fut().await, - | ^^^^^ await occurs here, with `Some(non_send())` maybe used later -... -LL | } - | - `Some(non_send())` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:74:17 - | -LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:49:15 - | -LL | let f: &mut std::fmt::Formatter = &mut get_formatter(); - | --------------- has type `Formatter<'_>` which is not `Send` -... -LL | fut().await; - | ^^^^^ await occurs here, with `get_formatter()` maybe used later -LL | } -LL | } - | - `get_formatter()` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr deleted file mode 100644 index b29d2e192f4f5..0000000000000 --- a/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr +++ /dev/null @@ -1,120 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:70:17 - | -LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:27:11 - | -LL | let x = non_send(); - | - has type `impl Debug` which is not `Send` -LL | drop(x); -LL | fut().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:72:17 - | -LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:36:26 - | -LL | match Some(non_send()) { - | ---------- has type `impl Debug` which is not `Send` -LL | Some(_) => fut().await, - | ^^^^^ await occurs here, with `non_send()` maybe used later -... -LL | } - | - `non_send()` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:74:17 - | -LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:49:15 - | -LL | let f: &mut std::fmt::Formatter = &mut get_formatter(); - | --------------- has type `Formatter<'_>` which is not `Send` -... -LL | fut().await; - | ^^^^^ await occurs here, with `get_formatter()` maybe used later -LL | } -LL | } - | - `get_formatter()` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:76:17 - | -LL | assert_send(non_sync_with_method_call_panic()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_panic` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:56:15 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut Formatter<'_>` which is not `Send` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:78:17 - | -LL | assert_send(non_sync_with_method_call_infinite_loop()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_infinite_loop` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:63:15 - | -LL | let f: &mut std::fmt::Formatter = loop {}; - | - has type `&mut Formatter<'_>` which is not `Send` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 - | -LL | fn assert_send(_: impl Send) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 5 previous errors - diff --git a/tests/ui/async-await/async-fn-nonsend.rs b/tests/ui/async-await/async-fn-nonsend.rs index ed440bd0182a6..c5453b67ef5b6 100644 --- a/tests/ui/async-await/async-fn-nonsend.rs +++ b/tests/ui/async-await/async-fn-nonsend.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 // compile-flags: --crate-type lib @@ -68,13 +65,10 @@ fn assert_send(_: impl Send) {} pub fn pass_assert() { assert_send(local_dropped_before_await()); - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely assert_send(non_send_temporary_in_match()); //~^ ERROR future cannot be sent between threads safely assert_send(non_sync_with_method_call()); //~^ ERROR future cannot be sent between threads safely assert_send(non_sync_with_method_call_panic()); - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely assert_send(non_sync_with_method_call_infinite_loop()); - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely } diff --git a/tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/async-fn-nonsend.stderr similarity index 88% rename from tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr rename to tests/ui/async-await/async-fn-nonsend.stderr index 219945e0971b9..0ced6c36f4715 100644 --- a/tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr +++ b/tests/ui/async-await/async-fn-nonsend.stderr @@ -1,32 +1,32 @@ error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:72:17 + --> $DIR/async-fn-nonsend.rs:68:17 | LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:36:26 + --> $DIR/async-fn-nonsend.rs:33:26 | LL | match Some(non_send()) { | ---------------- has type `Option` which is not `Send` LL | Some(_) => fut().await, | ^^^^^ await occurs here, with `Some(non_send())` maybe used later note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 + --> $DIR/async-fn-nonsend.rs:64:24 | LL | fn assert_send(_: impl Send) {} | ^^^^ required by this bound in `assert_send` error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:74:17 + --> $DIR/async-fn-nonsend.rs:70:17 | LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:49:15 + --> $DIR/async-fn-nonsend.rs:46:15 | LL | let f: &mut std::fmt::Formatter = &mut get_formatter(); | --------------- has type `Formatter<'_>` which is not `Send` @@ -34,7 +34,7 @@ LL | let f: &mut std::fmt::Formatter = &mut get_formatter(); LL | fut().await; | ^^^^^ await occurs here, with `get_formatter()` maybe used later note: required by a bound in `assert_send` - --> $DIR/async-fn-nonsend.rs:67:24 + --> $DIR/async-fn-nonsend.rs:64:24 | LL | fn assert_send(_: impl Send) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index c855e902ba93d..eaa455380505e 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -1,20 +1,19 @@ error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary - --> $DIR/async-is-unwindsafe.rs:12:19 + --> $DIR/async-is-unwindsafe.rs:12:5 | LL | is_unwindsafe(async { - | ___________________^ + | _____^^^^^^^^^^^^^_- + | | | + | | `&mut Context<'_>` may not be safely transferred across an unwind boundary LL | | LL | | use std::ptr::null; LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker}; ... | LL | | drop(cx_ref); LL | | }); - | | ^ - | | | - | |_____`&mut Context<'_>` may not be safely transferred across an unwind boundary - | within this `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]` + | |_____- within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}` | - = help: within `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` + = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>` note: future does not implement `UnwindSafe` as this value is used across an await --> $DIR/async-is-unwindsafe.rs:25:18 @@ -24,9 +23,6 @@ LL | let cx_ref = &mut cx; LL | LL | async {}.await; // this needs an inner await point | ^^^^^ await occurs here, with `cx_ref` maybe used later -... -LL | }); - | - `cx_ref` is later dropped here note: required by a bound in `is_unwindsafe` --> $DIR/async-is-unwindsafe.rs:3:26 | diff --git a/tests/ui/async-await/await-sequence.rs b/tests/ui/async-await/await-sequence.rs index 726c4284ec15e..79f68dd606cda 100644 --- a/tests/ui/async-await/await-sequence.rs +++ b/tests/ui/async-await/await-sequence.rs @@ -1,5 +1,4 @@ // edition:2021 -// compile-flags: -Z drop-tracking // build-pass use std::collections::HashMap; diff --git a/tests/ui/async-await/awaiting-unsized-param.rs b/tests/ui/async-await/awaiting-unsized-param.rs new file mode 100644 index 0000000000000..e8b18bf37f866 --- /dev/null +++ b/tests/ui/async-await/awaiting-unsized-param.rs @@ -0,0 +1,13 @@ +// edition: 2021 + +#![feature(unsized_fn_params, unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete + +use std::future::Future; + +async fn bug(mut f: dyn Future + Unpin) -> T { + //~^ ERROR the size for values of type `(dyn Future + Unpin + 'static)` cannot be known at compilation time + (&mut f).await +} + +fn main() {} diff --git a/tests/ui/async-await/awaiting-unsized-param.stderr b/tests/ui/async-await/awaiting-unsized-param.stderr new file mode 100644 index 0000000000000..47a5dcebf25d6 --- /dev/null +++ b/tests/ui/async-await/awaiting-unsized-param.stderr @@ -0,0 +1,21 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/awaiting-unsized-param.rs:3:31 + | +LL | #![feature(unsized_fn_params, unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `(dyn Future + Unpin + 'static)` cannot be known at compilation time + --> $DIR/awaiting-unsized-param.rs:8:17 + | +LL | async fn bug(mut f: dyn Future + Unpin) -> T { + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Future + Unpin + 'static)` + = note: all values captured by value by a closure must have a statically known size + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/const-async-fn-in-main.rs b/tests/ui/async-await/const-async-fn-in-main.rs new file mode 100644 index 0000000000000..5d1aa4d83f38e --- /dev/null +++ b/tests/ui/async-await/const-async-fn-in-main.rs @@ -0,0 +1,7 @@ +// edition:2021 +// Check what happens when a const async fn is in the main function (#102796) + +fn main() { + const async fn a() {} +//~^ ERROR functions cannot be both `const` and `async` +} diff --git a/tests/ui/async-await/const-async-fn-in-main.stderr b/tests/ui/async-await/const-async-fn-in-main.stderr new file mode 100644 index 0000000000000..10b15170922f7 --- /dev/null +++ b/tests/ui/async-await/const-async-fn-in-main.stderr @@ -0,0 +1,11 @@ +error: functions cannot be both `const` and `async` + --> $DIR/const-async-fn-in-main.rs:5:5 + | +LL | const async fn a() {} + | ^^^^^-^^^^^---------- + | | | + | | `async` because of this + | `const` because of this + +error: aborting due to previous error + diff --git a/tests/ui/async-await/default-struct-update.rs b/tests/ui/async-await/default-struct-update.rs index daee8469a1406..f4757e7cbaeb3 100644 --- a/tests/ui/async-await/default-struct-update.rs +++ b/tests/ui/async-await/default-struct-update.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // build-pass // edition:2018 diff --git a/tests/ui/async-await/drop-and-assign.rs b/tests/ui/async-await/drop-and-assign.rs index e520dfbdccebb..ef39033a9d4bb 100644 --- a/tests/ui/async-await/drop-and-assign.rs +++ b/tests/ui/async-await/drop-and-assign.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2021 // build-pass diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.rs b/tests/ui/async-await/drop-track-bad-field-in-fru.rs index 28ad7767583cf..667b288e676df 100644 --- a/tests/ui/async-await/drop-track-bad-field-in-fru.rs +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.rs @@ -1,4 +1,3 @@ -// compile-flags: -Zdrop-tracking // edition: 2021 fn main() {} diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr index b49b15db64cee..721e01062937e 100644 --- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -1,5 +1,5 @@ error[E0559]: variant `Option<_>::None` has no field named `value` - --> $DIR/drop-track-bad-field-in-fru.rs:7:12 + --> $DIR/drop-track-bad-field-in-fru.rs:6:12 | LL | None { value: (), ..Default::default() }.await; | ^^^^^ `Option<_>::None` does not have this field @@ -7,7 +7,7 @@ LL | None { value: (), ..Default::default() }.await; = note: all struct fields are already assigned error[E0277]: `Option<_>` is not a future - --> $DIR/drop-track-bad-field-in-fru.rs:7:46 + --> $DIR/drop-track-bad-field-in-fru.rs:6:46 | LL | None { value: (), ..Default::default() }.await; | -^^^^^ diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr deleted file mode 100644 index 80402d8424de0..0000000000000 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/drop-track-field-assign-nonsend.rs:45:17 - | -LL | assert_send(agent.handle()); - | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` -note: future is not `Send` as this value is used across an await - --> $DIR/drop-track-field-assign-nonsend.rs:23:39 - | -LL | let mut info = self.info_result.clone(); - | -------- has type `InfoResult` which is not `Send` -... -LL | let _ = send_element(element).await; - | ^^^^^ await occurs here, with `mut info` maybe used later -LL | } - | - `mut info` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/drop-track-field-assign-nonsend.rs:40:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr deleted file mode 100644 index 80402d8424de0..0000000000000 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/drop-track-field-assign-nonsend.rs:45:17 - | -LL | assert_send(agent.handle()); - | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` -note: future is not `Send` as this value is used across an await - --> $DIR/drop-track-field-assign-nonsend.rs:23:39 - | -LL | let mut info = self.info_result.clone(); - | -------- has type `InfoResult` which is not `Send` -... -LL | let _ = send_element(element).await; - | ^^^^^ await occurs here, with `mut info` maybe used later -LL | } - | - `mut info` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/drop-track-field-assign-nonsend.rs:40:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.rs b/tests/ui/async-await/drop-track-field-assign-nonsend.rs index 3e22280008fcf..19315ef19f90f 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.rs +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // Derived from an ICE found in tokio-xmpp during a crater run. // edition:2021 diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr similarity index 83% rename from tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr rename to tests/ui/async-await/drop-track-field-assign-nonsend.stderr index d9141cf4e3642..6c235916d647e 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/drop-track-field-assign-nonsend.rs:45:17 + --> $DIR/drop-track-field-assign-nonsend.rs:42:17 | LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc` note: future is not `Send` as this value is used across an await - --> $DIR/drop-track-field-assign-nonsend.rs:23:39 + --> $DIR/drop-track-field-assign-nonsend.rs:20:39 | LL | let mut info = self.info_result.clone(); | -------- has type `InfoResult` which is not `Send` @@ -14,7 +14,7 @@ LL | let mut info = self.info_result.clone(); LL | let _ = send_element(element).await; | ^^^^^ await occurs here, with `mut info` maybe used later note: required by a bound in `assert_send` - --> $DIR/drop-track-field-assign-nonsend.rs:40:19 + --> $DIR/drop-track-field-assign-nonsend.rs:37:19 | LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/async-await/drop-track-field-assign.rs b/tests/ui/async-await/drop-track-field-assign.rs index b79d2af066a37..4887eff7efa29 100644 --- a/tests/ui/async-await/drop-track-field-assign.rs +++ b/tests/ui/async-await/drop-track-field-assign.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // Derived from an ICE found in tokio-xmpp during a crater run. // edition:2021 // build-pass diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs index 7f72942958141..9f80b9c6e9f4b 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs @@ -1,4 +1,3 @@ -// compile-flags: -Zdrop-tracking // incremental // edition: 2021 @@ -99,8 +98,6 @@ fn main() { send(async { //~^ ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await }); } diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr index aa9a22e9e72ea..0d3ee8a93776b 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr @@ -1,26 +1,9 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + --> $DIR/drop-tracking-unresolved-typeck-results.rs:98:5 | LL | / send(async { LL | | LL | | -LL | | -LL | | -LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await -LL | | }); - | |______^ implementation of `FnOnce` is not general enough - | - = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&(),)>` - -error: implementation of `FnOnce` is not general enough - --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 - | -LL | / send(async { -LL | | -LL | | -LL | | -LL | | LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ implementation of `FnOnce` is not general enough @@ -29,34 +12,18 @@ LL | | }); = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough - --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + --> $DIR/drop-tracking-unresolved-typeck-results.rs:98:5 | LL | / send(async { LL | | LL | | -LL | | -LL | | -LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await -LL | | }); - | |______^ implementation of `FnOnce` is not general enough - | - = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&(),)>` - -error: implementation of `FnOnce` is not general enough - --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 - | -LL | / send(async { -LL | | -LL | | -LL | | -LL | | LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ implementation of `FnOnce` is not general enough | = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&(),)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/feature-self-return-type.rs b/tests/ui/async-await/feature-self-return-type.rs index 41f887430c1cb..ae6f766d247e6 100644 --- a/tests/ui/async-await/feature-self-return-type.rs +++ b/tests/ui/async-await/feature-self-return-type.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(impl_trait_projections)] // This test checks that we emit the correct borrowck error when `Self` is used as a return type. // See #61949 for context. diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr index 747c54b669440..dc160bfbf6179 100644 --- a/tests/ui/async-await/feature-self-return-type.stderr +++ b/tests/ui/async-await/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:22:18 + --> $DIR/feature-self-return-type.rs:21:18 | LL | let x = { | - borrow later stored here diff --git a/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr b/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr deleted file mode 100644 index e2e64c9ae0c4f..0000000000000 --- a/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/field-assign-nonsend.rs:45:17 - | -LL | assert_send(agent.handle()); - | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` -note: future is not `Send` as this value is used across an await - --> $DIR/field-assign-nonsend.rs:23:39 - | -LL | let mut info = self.info_result.clone(); - | -------- has type `InfoResult` which is not `Send` -... -LL | let _ = send_element(element).await; - | ^^^^^ await occurs here, with `mut info` maybe used later -LL | } - | - `mut info` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/field-assign-nonsend.rs:40:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr deleted file mode 100644 index e2e64c9ae0c4f..0000000000000 --- a/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/field-assign-nonsend.rs:45:17 - | -LL | assert_send(agent.handle()); - | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` - | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` -note: future is not `Send` as this value is used across an await - --> $DIR/field-assign-nonsend.rs:23:39 - | -LL | let mut info = self.info_result.clone(); - | -------- has type `InfoResult` which is not `Send` -... -LL | let _ = send_element(element).await; - | ^^^^^ await occurs here, with `mut info` maybe used later -LL | } - | - `mut info` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/field-assign-nonsend.rs:40:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/field-assign-nonsend.rs b/tests/ui/async-await/field-assign-nonsend.rs index 3e22280008fcf..19315ef19f90f 100644 --- a/tests/ui/async-await/field-assign-nonsend.rs +++ b/tests/ui/async-await/field-assign-nonsend.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // Derived from an ICE found in tokio-xmpp during a crater run. // edition:2021 diff --git a/tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/field-assign-nonsend.stderr similarity index 86% rename from tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr rename to tests/ui/async-await/field-assign-nonsend.stderr index d1df8e91afa2c..3037d7024472d 100644 --- a/tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr +++ b/tests/ui/async-await/field-assign-nonsend.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/field-assign-nonsend.rs:45:17 + --> $DIR/field-assign-nonsend.rs:42:17 | LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc` note: future is not `Send` as this value is used across an await - --> $DIR/field-assign-nonsend.rs:23:39 + --> $DIR/field-assign-nonsend.rs:20:39 | LL | let mut info = self.info_result.clone(); | -------- has type `InfoResult` which is not `Send` @@ -14,7 +14,7 @@ LL | let mut info = self.info_result.clone(); LL | let _ = send_element(element).await; | ^^^^^ await occurs here, with `mut info` maybe used later note: required by a bound in `assert_send` - --> $DIR/field-assign-nonsend.rs:40:19 + --> $DIR/field-assign-nonsend.rs:37:19 | LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/async-await/field-assign.rs b/tests/ui/async-await/field-assign.rs index b79d2af066a37..4887eff7efa29 100644 --- a/tests/ui/async-await/field-assign.rs +++ b/tests/ui/async-await/field-assign.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // Derived from an ICE found in tokio-xmpp during a crater run. // edition:2021 // build-pass diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout index c0fbb0204b307..d63911b0d3c19 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout @@ -1,11 +1,17 @@ -print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2]`: 3078 bytes, alignment: 1 bytes +print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`: 3078 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 3077 bytes print-type-size local `.__awaitee`: 3077 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]`: 3077 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes +print-type-size field `.value`: 3077 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 3077 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 3077 bytes +print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}`: 3077 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes @@ -30,13 +36,13 @@ print-type-size variant `Returned`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]>`: 3077 bytes, alignment: 1 bytes -print-type-size field `.value`: 3077 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]>`: 3077 bytes, alignment: 1 bytes -print-type-size variant `MaybeUninit`: 3077 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes -print-type-size field `.value`: 3077 bytes -print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]`: 1025 bytes, alignment: 1 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}`: 1025 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.arg`: 1024 bytes @@ -44,17 +50,6 @@ print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.arg`: 1024 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.arg`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]>`: 1025 bytes, alignment: 1 bytes -print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]>`: 1025 bytes, alignment: 1 bytes -print-type-size variant `MaybeUninit`: 1025 bytes -print-type-size field `.uninit`: 0 bytes -print-type-size field `.value`: 1025 bytes -print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes -print-type-size discriminant: 1 bytes -print-type-size variant `Unresumed`: 0 bytes -print-type-size variant `Returned`: 0 bytes -print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes print-type-size type: `std::mem::MaybeUninit`: 1 bytes, alignment: 1 bytes @@ -66,3 +61,8 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Pending`: 0 bytes +print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}`: 1 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index b5e95ddd7100d..005460df626fc 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -1,55 +1,47 @@ -print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes +print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 3075 bytes print-type-size local `.__awaitee`: 3075 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes -print-type-size discriminant: 1 bytes -print-type-size variant `Unresumed`: 1024 bytes -print-type-size upvar `.t`: 1024 bytes -print-type-size variant `Suspend0`: 3074 bytes -print-type-size upvar `.t`: 1024 bytes -print-type-size local `.__awaitee`: 2050 bytes -print-type-size variant `Returned`: 1024 bytes -print-type-size upvar `.t`: 1024 bytes -print-type-size variant `Panicked`: 1024 bytes -print-type-size upvar `.t`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3075 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes +print-type-size type: `{async fn body@$DIR/large-arg.rs:10:30: 12:2}`: 3075 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size variant `Suspend0`: 2049 bytes +print-type-size variant `Suspend0`: 3074 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size local `.__awaitee`: 1025 bytes +print-type-size local `.__awaitee`: 2050 bytes print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 2050 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes +print-type-size type: `{async fn body@$DIR/large-arg.rs:13:26: 15:2}`: 2050 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.t`: 1024 bytes +print-type-size variant `Suspend0`: 2049 bytes +print-type-size upvar `.t`: 1024 bytes +print-type-size local `.__awaitee`: 1025 bytes print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1025 bytes @@ -58,3 +50,11 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 1024 bytes print-type-size field `.0`: 1024 bytes print-type-size variant `Pending`: 0 bytes +print-type-size type: `{async fn body@$DIR/large-arg.rs:16:26: 18:2}`: 1025 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes diff --git a/tests/ui/async-await/generator-desc.stderr b/tests/ui/async-await/generator-desc.stderr index 042766f19ca90..d3e951cfe49f5 100644 --- a/tests/ui/async-await/generator-desc.stderr +++ b/tests/ui/async-await/generator-desc.stderr @@ -7,8 +7,8 @@ LL | fun(async {}, async {}); | | the expected `async` block | arguments to this function are incorrect | - = note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]` - found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]` + = note: expected `async` block `{async block@$DIR/generator-desc.rs:10:9: 10:17}` + found `async` block `{async block@$DIR/generator-desc.rs:10:19: 10:27}` note: function defined here --> $DIR/generator-desc.rs:8:4 | @@ -40,8 +40,8 @@ LL | fun((async || {})(), (async || {})()); | | the expected `async` closure body | arguments to this function are incorrect | - = note: expected `async` closure body `[async closure body@$DIR/generator-desc.rs:14:19: 14:21]` - found `async` closure body `[async closure body@$DIR/generator-desc.rs:14:36: 14:38]` + = note: expected `async` closure body `{async closure body@$DIR/generator-desc.rs:14:19: 14:21}` + found `async` closure body `{async closure body@$DIR/generator-desc.rs:14:36: 14:38}` note: function defined here --> $DIR/generator-desc.rs:8:4 | diff --git a/tests/ui/async-await/generator-not-future.stderr b/tests/ui/async-await/generator-not-future.stderr index 1b81b461f0aad..540501b982668 100644 --- a/tests/ui/async-await/generator-not-future.stderr +++ b/tests/ui/async-await/generator-not-future.stderr @@ -26,11 +26,11 @@ note: required by a bound in `takes_generator` LL | fn takes_generator(_g: impl Generator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator` -error[E0277]: the trait bound `[async block@$DIR/generator-not-future.rs:35:21: 35:29]: Generator<_>` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/generator-not-future.rs:35:21: 35:29}: Generator<_>` is not satisfied --> $DIR/generator-not-future.rs:35:21 | LL | takes_generator(async {}); - | --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `[async block@$DIR/generator-not-future.rs:35:21: 35:29]` + | --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `{async block@$DIR/generator-not-future.rs:35:21: 35:29}` | | | required by a bound introduced by this call | @@ -56,7 +56,7 @@ note: required by a bound in `takes_future` LL | fn takes_future(_f: impl Future) {} | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` -error[E0277]: `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future +error[E0277]: `{generator@$DIR/generator-not-future.rs:41:18: 41:23}` is not a future --> $DIR/generator-not-future.rs:41:18 | LL | takes_future(|ctx| { @@ -66,10 +66,10 @@ LL | takes_future(|ctx| { LL | | LL | | ctx = yield (); LL | | }); - | |_____^ `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future + | |_____^ `{generator@$DIR/generator-not-future.rs:41:18: 41:23}` is not a future | - = help: the trait `Future` is not implemented for `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` - = note: [generator@$DIR/generator-not-future.rs:41:18: 41:23] must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for `{generator@$DIR/generator-not-future.rs:41:18: 41:23}` + = note: {generator@$DIR/generator-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `takes_future` --> $DIR/generator-not-future.rs:17:26 | diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs index 974f5aaff83c3..14f18811c1e23 100644 --- a/tests/ui/async-await/in-trait/async-associated-types.rs +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -2,7 +2,6 @@ // edition: 2021 #![feature(async_fn_in_trait)] -#![feature(impl_trait_projections)] #![allow(incomplete_features)] use std::fmt::Debug; @@ -10,12 +9,14 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b { type MyAssoc; + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> Self::MyAssoc; } impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { type MyAssoc = (&'a U, &'b T); + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { (self, key) } diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 06413fe6f8277..8143f0bca0315 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -6,10 +6,12 @@ use std::future::Future; trait AsyncTrait { + #[allow(async_fn_in_trait)] async fn default_impl() { assert!(false); } + #[allow(async_fn_in_trait)] async fn call_default_impl() { Self::default_impl().await } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr index 168ef8e9ee4e7..3f1f1766eb58e 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -1,8 +1,8 @@ error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28 + --> $DIR/async-example-desugared-boxed-in-trait.rs:15:5 | LL | async fn foo(&self) -> i32 { - | ^^^ expected `Pin>>`, found future + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin>>`, found future | note: type in trait --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22 diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index 3505690f1ec7a..5d5aa817b4cb1 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -10,6 +10,7 @@ use std::pin::Pin; use std::task::Poll; pub trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs index 0a5023176fef7..7987645c97b22 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared.rs @@ -8,6 +8,7 @@ use std::future::Future; trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs index abf94ef7450fc..8c80c21eabec4 100644 --- a/tests/ui/async-await/in-trait/async-example.rs +++ b/tests/ui/async-await/in-trait/async-example.rs @@ -5,7 +5,10 @@ #![allow(incomplete_features)] trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; + + #[allow(async_fn_in_trait)] async fn bar(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr index 5c8d64fc6cb4c..965c385e9bc7f 100644 --- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -1,36 +1,30 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics-and-bounds.rs:12:28 + --> $DIR/async-generics-and-bounds.rs:12:5 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^^^^^^^ + | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | the parameter type `U` must be valid for the anonymous lifetime as defined here... + | ...so that the reference type `&(T, U)` does not outlive the data it points at | -note: the parameter type `U` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics-and-bounds.rs:12:18 +help: consider adding an explicit lifetime bound | -LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^ -note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics-and-bounds.rs:12:28 - | -LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^^^^^^^ +LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, U: 'a; + | ++++ ++ ++ +++++++ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics-and-bounds.rs:12:28 + --> $DIR/async-generics-and-bounds.rs:12:5 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^^^^^^^ + | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | the parameter type `T` must be valid for the anonymous lifetime as defined here... + | ...so that the reference type `&(T, U)` does not outlive the data it points at | -note: the parameter type `T` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics-and-bounds.rs:12:18 +help: consider adding an explicit lifetime bound | -LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^ -note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics-and-bounds.rs:12:28 - | -LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; - | ^^^^^^^ +LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, T: 'a; + | ++++ ++ ++ +++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr index 6ae73d9e3a601..20c2491e9d0c7 100644 --- a/tests/ui/async-await/in-trait/async-generics.stderr +++ b/tests/ui/async-await/in-trait/async-generics.stderr @@ -1,36 +1,30 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics.rs:9:28 + --> $DIR/async-generics.rs:9:5 | LL | async fn foo(&self) -> &(T, U); - | ^^^^^^^ + | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^ + | | | + | | the parameter type `U` must be valid for the anonymous lifetime as defined here... + | ...so that the reference type `&(T, U)` does not outlive the data it points at | -note: the parameter type `U` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics.rs:9:18 +help: consider adding an explicit lifetime bound | -LL | async fn foo(&self) -> &(T, U); - | ^ -note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics.rs:9:28 - | -LL | async fn foo(&self) -> &(T, U); - | ^^^^^^^ +LL | async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a; + | ++++ ++ ++ +++++++++++ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics.rs:9:28 + --> $DIR/async-generics.rs:9:5 | LL | async fn foo(&self) -> &(T, U); - | ^^^^^^^ + | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^ + | | | + | | the parameter type `T` must be valid for the anonymous lifetime as defined here... + | ...so that the reference type `&(T, U)` does not outlive the data it points at | -note: the parameter type `T` must be valid for the anonymous lifetime as defined here... - --> $DIR/async-generics.rs:9:18 +help: consider adding an explicit lifetime bound | -LL | async fn foo(&self) -> &(T, U); - | ^ -note: ...so that the reference type `&(T, U)` does not outlive the data it points at - --> $DIR/async-generics.rs:9:28 - | -LL | async fn foo(&self) -> &(T, U); - | ^^^^^^^ +LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: 'a; + | ++++ ++ ++ +++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs index d5481d277e40a..96cda4e35da78 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> { + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; } diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs index f298e45d2390b..4b0264bc8d017 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] trait MyTrait<'a, 'b, T> { + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); } diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr index cab173bdd5b70..6897bf1c99943 100644 --- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr +++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr @@ -1,8 +1,8 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/async-recursive-generic.rs:11:48 + --> $DIR/async-recursive-generic.rs:11:5 | LL | async fn foo_recursive(&self, n: usize) -> T { - | ^ recursive `async fn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn` | = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr index 9feff37b3fe46..c9b4784e3b405 100644 --- a/tests/ui/async-await/in-trait/async-recursive.stderr +++ b/tests/ui/async-await/in-trait/async-recursive.stderr @@ -1,8 +1,8 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/async-recursive.rs:11:48 + --> $DIR/async-recursive.rs:11:5 | LL | async fn foo_recursive(&self, n: usize) -> i32 { - | ^^^ recursive `async fn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn` | = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion diff --git a/tests/ui/async-await/in-trait/auxiliary/foreign-async-fn.rs b/tests/ui/async-await/in-trait/auxiliary/foreign-async-fn.rs new file mode 100644 index 0000000000000..bba886f175ee6 --- /dev/null +++ b/tests/ui/async-await/in-trait/auxiliary/foreign-async-fn.rs @@ -0,0 +1,7 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] + +pub trait Foo { + async fn test(); +} diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 7c750bf510182..4ba6d4cba0cb3 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -1,14 +1,14 @@ error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/dont-project-to-specializable-projection.rs:14:35 + --> $DIR/dont-project-to-specializable-projection.rs:14:5 | LL | default async fn foo(_: T) -> &'static str { - | ^^^^^^^^^^^^ expected associated type, found future + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found future | note: type in trait - --> $DIR/dont-project-to-specializable-projection.rs:10:27 + --> $DIR/dont-project-to-specializable-projection.rs:10:5 | LL | async fn foo(_: T) -> &'static str; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature `fn(_) -> impl Future` found signature `fn(_) -> impl Future` diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs index 6b3b142014bd3..bc410cc29546d 100644 --- a/tests/ui/async-await/in-trait/early-bound-1.rs +++ b/tests/ui/async-await/in-trait/early-bound-1.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn foo(&mut self); } diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs index 270443229b054..1974b1d9f7a4f 100644 --- a/tests/ui/async-await/in-trait/early-bound-2.rs +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn foo(&mut self); } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs index 78017429f73d5..e1703415dbd5a 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -11,7 +11,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> impl Future { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types async { *self } } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr index 37d9669c0124b..a7c897f786e4a 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types --> $DIR/fn-not-async-err2.rs:13:22 | LL | fn foo(&self) -> impl Future { diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs index 52bceb3cc5cd6..40eebad86c27c 100644 --- a/tests/ui/async-await/in-trait/implied-bounds.rs +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -7,6 +7,8 @@ trait TcpStack { type Connection<'a>: Sized where Self: 'a; fn connect<'a>(&'a self) -> Self::Connection<'a>; + + #[allow(async_fn_in_trait)] async fn async_connect<'a>(&'a self) -> Self::Connection<'a>; } diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs index 85d17ddff94d8..2fe6b473df670 100644 --- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs @@ -1,6 +1,6 @@ // edition: 2021 // build-fail -//~^^ ERROR overflow evaluating the requirement `::{opaque#0} == _` +//~^^ ERROR cycle detected when computing layout of #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr index 3f487a6e5fe58..41e84466a144e 100644 --- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr @@ -1,5 +1,10 @@ -error[E0275]: overflow evaluating the requirement `::{opaque#0} == _` +error[E0391]: cycle detected when computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:35:27: 37:6}` + | + = note: ...which requires computing layout of `<::Second as Second>::{opaque#0}`... + = note: ...which again requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:35:27: 37:6}`, completing the cycle + = note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:8:13: 10:6}` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs index f61b34ed99e00..3d9cef0210faa 100644 --- a/tests/ui/async-await/in-trait/issue-102138.rs +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -10,6 +10,8 @@ async fn yield_now() {} trait AsyncIterator { type Item; + + #[allow(async_fn_in_trait)] async fn next(&mut self) -> Option; } diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs index 9a35f6515cb1a..4a23e4be4f710 100644 --- a/tests/ui/async-await/in-trait/issue-102219.rs +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -6,5 +6,6 @@ #![allow(incomplete_features)] trait T { + #[allow(async_fn_in_trait)] async fn foo(); } diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs index 49c3e9feeb4c4..327d432a6a6d1 100644 --- a/tests/ui/async-await/in-trait/issue-102310.rs +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait SpiDevice { + #[allow(async_fn_in_trait)] async fn transaction(&mut self); } diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index e396df4e5d119..0a33470750544 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -8,6 +8,7 @@ use std::future::Future; pub trait Pool { type Conn; + #[allow(async_fn_in_trait)] async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future>( &'a self, callback: F, diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.stderr index f6aba1fcdbf8f..87a7e85bfbbb8 100644 --- a/tests/ui/async-await/in-trait/missing-feature-flag.stderr +++ b/tests/ui/async-await/in-trait/missing-feature-flag.stderr @@ -7,6 +7,12 @@ LL | async fn foo(_: T) -> &'static str; LL | impl MyTrait for MyStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:16:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/missing-feature-flag.rs:16:5 | @@ -18,12 +24,6 @@ LL | async fn foo(_: i32) -> &'static str {} | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error[E0308]: mismatched types - --> $DIR/missing-feature-flag.rs:16: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. diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr index 18185b75554af..7e59d94d456df 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -15,6 +15,11 @@ note: required by a bound in `assert_is_send` | LL | fn assert_is_send(_: impl Send) {} | ^^^^ required by this bound in `assert_is_send` +help: `Send` can be made part of the associated future's guarantees for all implementations of `Foo::bar` + | +LL - async fn bar(); +LL + fn bar() -> impl std::future::Future + Send; + | error: aborting due to previous error diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs index 9cdc23bbc7809..8c43e1b07e297 100644 --- a/tests/ui/async-await/in-trait/nested-rpit.rs +++ b/tests/ui/async-await/in-trait/nested-rpit.rs @@ -9,6 +9,7 @@ use std::future::Future; use std::marker::PhantomData; trait Lockable { + #[allow(async_fn_in_trait)] async fn lock_all_entries(&self) -> impl Future>; } diff --git a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs index c4008f2b7e7ad..f8fe0d1bde88e 100644 --- a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs +++ b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs @@ -11,6 +11,7 @@ pub struct SharedState {} pub trait State { + #[allow(async_fn_in_trait)] async fn execute(self, shared_state: &SharedState); } diff --git a/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.fixed b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.fixed new file mode 100644 index 0000000000000..33c0058743970 --- /dev/null +++ b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.fixed @@ -0,0 +1,20 @@ +// run-rustfix +// edition: 2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(unused)] + +trait Foo { + fn test() -> impl std::future::Future + Send { async {} } + fn test2() -> impl std::future::Future + Send {async { 1 + 2 } } +} + +fn bar() { + fn needs_send(_: impl Send) {} + needs_send(T::test()); + //~^ ERROR `impl Future` cannot be sent between threads safely + needs_send(T::test2()); + //~^ ERROR `impl Future` cannot be sent between threads safely +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.rs b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.rs new file mode 100644 index 0000000000000..96b623d6988f7 --- /dev/null +++ b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.rs @@ -0,0 +1,20 @@ +// run-rustfix +// edition: 2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(unused)] + +trait Foo { + async fn test() -> () {} + async fn test2() -> i32 { 1 + 2 } +} + +fn bar() { + fn needs_send(_: impl Send) {} + needs_send(T::test()); + //~^ ERROR `impl Future` cannot be sent between threads safely + needs_send(T::test2()); + //~^ ERROR `impl Future` cannot be sent between threads safely +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.stderr b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.stderr new file mode 100644 index 0000000000000..4319a14118b96 --- /dev/null +++ b/tests/ui/async-await/in-trait/send-on-async-fn-in-trait.stderr @@ -0,0 +1,43 @@ +error[E0277]: `impl Future` cannot be sent between threads safely + --> $DIR/send-on-async-fn-in-trait.rs:14:16 + | +LL | needs_send(T::test()); + | ---------- ^^^^^^^^^ `impl Future` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `impl Future` +note: required by a bound in `needs_send` + --> $DIR/send-on-async-fn-in-trait.rs:13:27 + | +LL | fn needs_send(_: impl Send) {} + | ^^^^ required by this bound in `needs_send` +help: `Send` can be made part of the associated future's guarantees for all implementations of `Foo::test` + | +LL - async fn test() -> () {} +LL + fn test() -> impl std::future::Future + Send { async {} } + | + +error[E0277]: `impl Future` cannot be sent between threads safely + --> $DIR/send-on-async-fn-in-trait.rs:16:16 + | +LL | needs_send(T::test2()); + | ---------- ^^^^^^^^^^ `impl Future` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `impl Future` +note: required by a bound in `needs_send` + --> $DIR/send-on-async-fn-in-trait.rs:13:27 + | +LL | fn needs_send(_: impl Send) {} + | ^^^^ required by this bound in `needs_send` +help: `Send` can be made part of the associated future's guarantees for all implementations of `Foo::test2` + | +LL - async fn test2() -> i32 { 1 + 2 } +LL + fn test2() -> impl std::future::Future + Send {async { 1 + 2 } } + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.rs b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.rs new file mode 100644 index 0000000000000..83b69d72a9609 --- /dev/null +++ b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.rs @@ -0,0 +1,15 @@ +// aux-build:foreign-async-fn.rs +// edition:2021 + +#![feature(async_fn_in_trait)] + +extern crate foreign_async_fn; +use foreign_async_fn::Foo; + +fn bar() { + fn needs_send(_: impl Send) {} + needs_send(T::test()); + //~^ ERROR `impl Future` cannot be sent between threads safely +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr new file mode 100644 index 0000000000000..f337a04ba1945 --- /dev/null +++ b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr @@ -0,0 +1,23 @@ +error[E0277]: `impl Future` cannot be sent between threads safely + --> $DIR/send-on-foreign-async-fn-in-trait.rs:11:16 + | +LL | needs_send(T::test()); + | ---------- ^^^^^^^^^ `impl Future` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `impl Future` +note: `::test` is an `async fn` in trait, which does not automatically imply that its future is `Send` + --> $DIR/auxiliary/foreign-async-fn.rs:6:5 + | +LL | async fn test(); + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `needs_send` + --> $DIR/send-on-foreign-async-fn-in-trait.rs:10:27 + | +LL | fn needs_send(_: impl Send) {} + | ^^^^ required by this bound in `needs_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/in-trait/warn.rs b/tests/ui/async-await/in-trait/warn.rs new file mode 100644 index 0000000000000..4f981c31f5c06 --- /dev/null +++ b/tests/ui/async-await/in-trait/warn.rs @@ -0,0 +1,23 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![deny(async_fn_in_trait)] + +pub trait Foo { + async fn not_send(); + //~^ ERROR use of `async fn` in public traits is discouraged +} + +mod private { + pub trait FooUnreachable { + async fn not_send(); + // No warning + } +} + +pub(crate) trait FooCrate { + async fn not_send(); + // No warning +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/warn.stderr b/tests/ui/async-await/in-trait/warn.stderr new file mode 100644 index 0000000000000..eac41a6e92425 --- /dev/null +++ b/tests/ui/async-await/in-trait/warn.stderr @@ -0,0 +1,20 @@ +error: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified + --> $DIR/warn.rs:7:5 + | +LL | async fn not_send(); + | ^^^^^ + | + = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` +note: the lint level is defined here + --> $DIR/warn.rs:4:9 + | +LL | #![deny(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ +help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send` + | +LL - async fn not_send(); +LL + fn not_send() -> impl std::future::Future + Send; + | + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-108572.fixed b/tests/ui/async-await/issue-108572.fixed new file mode 100644 index 0000000000000..8f0133d97b547 --- /dev/null +++ b/tests/ui/async-await/issue-108572.fixed @@ -0,0 +1,16 @@ +// edition: 2021 +// run-rustfix +#![allow(unused_must_use, dead_code)] + +use std::future::Future; +fn foo() -> impl Future { + async { } +} + +fn bar(cx: &mut std::task::Context<'_>) { + let fut = foo(); + let mut pinned = std::pin::pin!(fut); + pinned.as_mut().poll(cx); + //~^ ERROR no method named `poll` found for opaque type `impl Future` in the current scope [E0599] +} +fn main() {} diff --git a/tests/ui/async-await/issue-108572.rs b/tests/ui/async-await/issue-108572.rs index efcb8b8ebab0a..3596580763c5a 100644 --- a/tests/ui/async-await/issue-108572.rs +++ b/tests/ui/async-await/issue-108572.rs @@ -1,12 +1,15 @@ // edition: 2021 +// run-rustfix +#![allow(unused_must_use, dead_code)] use std::future::Future; fn foo() -> impl Future { async { } } -fn main() { +fn bar(cx: &mut std::task::Context<'_>) { let fut = foo(); - fut.poll(); + fut.poll(cx); //~^ ERROR no method named `poll` found for opaque type `impl Future` in the current scope [E0599] } +fn main() {} diff --git a/tests/ui/async-await/issue-108572.stderr b/tests/ui/async-await/issue-108572.stderr index 0dbcf4d660a98..588669092b01c 100644 --- a/tests/ui/async-await/issue-108572.stderr +++ b/tests/ui/async-await/issue-108572.stderr @@ -1,11 +1,16 @@ error[E0599]: no method named `poll` found for opaque type `impl Future` in the current scope - --> $DIR/issue-108572.rs:10:9 + --> $DIR/issue-108572.rs:12:9 | -LL | fut.poll(); +LL | fut.poll(cx); | ^^^^ method not found in `impl Future` | = help: method `poll` found on `Pin<&mut impl Future>`, see documentation for `std::pin::Pin` = help: self type must be pinned to call `Future::poll`, see https://rust-lang.github.io/async-book/04_pinning/01_chapter.html#pinning-in-practice +help: consider pinning the expression + | +LL ~ let mut pinned = std::pin::pin!(fut); +LL ~ pinned.as_mut().poll(cx); + | error: aborting due to previous error diff --git a/tests/ui/async-await/issue-61949-self-return-type.rs b/tests/ui/async-await/issue-61949-self-return-type.rs deleted file mode 100644 index d73dbc6e828f3..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// edition:2018 -// gate-test-impl_trait_projections - -// This test checks that `Self` is prohibited as a return type. See #61949 for context. - -pub struct Foo<'a> { - pub bar: &'a i32, -} - -impl<'a> Foo<'a> { - pub async fn new(_bar: &'a i32) -> Self { - //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - Foo { - bar: &22 - } - } -} - -async fn foo() { - let x = { - let bar = 22; - Foo::new(&bar).await - //~^ ERROR `bar` does not live long enough - }; - drop(x); -} - -fn main() { } diff --git a/tests/ui/async-await/issue-61949-self-return-type.stderr b/tests/ui/async-await/issue-61949-self-return-type.stderr deleted file mode 100644 index ac85ed2887abc..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-61949-self-return-type.rs:11:40 - | -LL | pub async fn new(_bar: &'a i32) -> Self { - | ^^^^ help: consider spelling out the type instead: `Foo<'a>` - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - -error[E0597]: `bar` does not live long enough - --> $DIR/issue-61949-self-return-type.rs:22:18 - | -LL | let x = { - | - borrow later stored here -LL | let bar = 22; - | --- binding `bar` declared here -LL | Foo::new(&bar).await - | ^^^^ borrowed value does not live long enough -LL | -LL | }; - | - `bar` dropped here while still borrowed - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0597, E0658. -For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr b/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr deleted file mode 100644 index 56aa035f44bab..0000000000000 --- a/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be shared between threads safely - --> $DIR/issue-64130-1-sync.rs:25:13 - | -LL | is_sync(bar()); - | ^^^^^ future returned by `bar` is not `Sync` - | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` -note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:18:11 - | -LL | let x = Foo; - | - has type `Foo` which is not `Sync` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | drop(x); -LL | } - | - `x` is later dropped here -note: required by a bound in `is_sync` - --> $DIR/issue-64130-1-sync.rs:14:15 - | -LL | fn is_sync(t: T) { } - | ^^^^ required by this bound in `is_sync` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr deleted file mode 100644 index 56aa035f44bab..0000000000000 --- a/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: future cannot be shared between threads safely - --> $DIR/issue-64130-1-sync.rs:25:13 - | -LL | is_sync(bar()); - | ^^^^^ future returned by `bar` is not `Sync` - | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` -note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:18:11 - | -LL | let x = Foo; - | - has type `Foo` which is not `Sync` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | drop(x); -LL | } - | - `x` is later dropped here -note: required by a bound in `is_sync` - --> $DIR/issue-64130-1-sync.rs:14:15 - | -LL | fn is_sync(t: T) { } - | ^^^^ required by this bound in `is_sync` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-1-sync.rs b/tests/ui/async-await/issue-64130-1-sync.rs index 44646e0e5f27b..7769085a0db8e 100644 --- a/tests/ui/async-await/issue-64130-1-sync.rs +++ b/tests/ui/async-await/issue-64130-1-sync.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(negative_impls)] // edition:2018 diff --git a/tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr similarity index 84% rename from tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-64130-1-sync.stderr index ea1bfb9f9ac23..207e085d273f0 100644 --- a/tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-64130-1-sync.stderr @@ -1,19 +1,19 @@ error: future cannot be shared between threads safely - --> $DIR/issue-64130-1-sync.rs:25:13 + --> $DIR/issue-64130-1-sync.rs:22:13 | LL | is_sync(bar()); | ^^^^^ future returned by `bar` is not `Sync` | = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:18:11 + --> $DIR/issue-64130-1-sync.rs:15:11 | LL | let x = Foo; | - has type `Foo` which is not `Sync` LL | baz().await; | ^^^^^ await occurs here, with `x` maybe used later note: required by a bound in `is_sync` - --> $DIR/issue-64130-1-sync.rs:14:15 + --> $DIR/issue-64130-1-sync.rs:11:15 | LL | fn is_sync(t: T) { } | ^^^^ required by this bound in `is_sync` diff --git a/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr b/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr deleted file mode 100644 index d1717ad3310ab..0000000000000 --- a/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-64130-2-send.rs:24:13 - | -LL | is_send(bar()); - | ^^^^^ future returned by `bar` is not `Send` - | - = note: the trait bound `Unique: Send` is not satisfied -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:18:11 - | -LL | let x = Box::new(Foo); - | - has type `Box` which is not `Send` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here -note: required by a bound in `is_send` - --> $DIR/issue-64130-2-send.rs:14:15 - | -LL | fn is_send(t: T) { } - | ^^^^ required by this bound in `is_send` -help: consider borrowing here - | -LL | is_send(&bar()); - | + - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr deleted file mode 100644 index d1717ad3310ab..0000000000000 --- a/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-64130-2-send.rs:24:13 - | -LL | is_send(bar()); - | ^^^^^ future returned by `bar` is not `Send` - | - = note: the trait bound `Unique: Send` is not satisfied -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:18:11 - | -LL | let x = Box::new(Foo); - | - has type `Box` which is not `Send` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here -note: required by a bound in `is_send` - --> $DIR/issue-64130-2-send.rs:14:15 - | -LL | fn is_send(t: T) { } - | ^^^^ required by this bound in `is_send` -help: consider borrowing here - | -LL | is_send(&bar()); - | + - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-2-send.rs b/tests/ui/async-await/issue-64130-2-send.rs index d6d855bac0762..0195afe6b3924 100644 --- a/tests/ui/async-await/issue-64130-2-send.rs +++ b/tests/ui/async-await/issue-64130-2-send.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(negative_impls)] // edition:2018 @@ -14,8 +11,9 @@ impl !Send for Foo {} fn is_send(t: T) { } async fn bar() { - let x = Box::new(Foo); + let x = Foo; baz().await; + drop(x); } async fn baz() { } diff --git a/tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-2-send.stderr similarity index 58% rename from tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-64130-2-send.stderr index 45e43525a206a..a433c76ae7088 100644 --- a/tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-64130-2-send.stderr @@ -1,26 +1,22 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-2-send.rs:24:13 + --> $DIR/issue-64130-2-send.rs:22:13 | LL | is_send(bar()); | ^^^^^ future returned by `bar` is not `Send` | - = note: the trait bound `Unique: Send` is not satisfied + = help: within `impl Future`, the trait `Send` is not implemented for `Foo` note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:18:11 + --> $DIR/issue-64130-2-send.rs:15:11 | -LL | let x = Box::new(Foo); - | - has type `Box` which is not `Send` +LL | let x = Foo; + | - has type `Foo` which is not `Send` LL | baz().await; | ^^^^^ await occurs here, with `x` maybe used later note: required by a bound in `is_send` - --> $DIR/issue-64130-2-send.rs:14:15 + --> $DIR/issue-64130-2-send.rs:11:15 | LL | fn is_send(t: T) { } | ^^^^ required by this bound in `is_send` -help: consider borrowing here - | -LL | is_send(&bar()); - | + error: aborting due to previous error diff --git a/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr b/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr deleted file mode 100644 index b69f06da1cde5..0000000000000 --- a/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` - --> $DIR/issue-64130-3-other.rs:27:12 - | -LL | async fn bar() { - | - within this `impl Future` -... -LL | is_qux(bar()); - | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` - | -note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:21:11 - | -LL | let x = Box::new(Foo); - | - has type `Box` which does not implement `Qux` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here -note: required by a bound in `is_qux` - --> $DIR/issue-64130-3-other.rs:17:14 - | -LL | fn is_qux(t: T) {} - | ^^^ required by this bound in `is_qux` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr deleted file mode 100644 index b69f06da1cde5..0000000000000 --- a/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` - --> $DIR/issue-64130-3-other.rs:27:12 - | -LL | async fn bar() { - | - within this `impl Future` -... -LL | is_qux(bar()); - | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` - | -note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:21:11 - | -LL | let x = Box::new(Foo); - | - has type `Box` which does not implement `Qux` -LL | baz().await; - | ^^^^^ await occurs here, with `x` maybe used later -LL | } - | - `x` is later dropped here -note: required by a bound in `is_qux` - --> $DIR/issue-64130-3-other.rs:17:14 - | -LL | fn is_qux(t: T) {} - | ^^^ required by this bound in `is_qux` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-64130-3-other.rs b/tests/ui/async-await/issue-64130-3-other.rs index 92d3b7c81fb62..074d67aa3fb87 100644 --- a/tests/ui/async-await/issue-64130-3-other.rs +++ b/tests/ui/async-await/issue-64130-3-other.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(auto_traits)] #![feature(negative_impls)] // edition:2018 @@ -17,8 +14,9 @@ impl !Qux for Foo {} fn is_qux(t: T) {} async fn bar() { - let x = Box::new(Foo); + let x = Foo; baz().await; + drop(x); } async fn baz() {} diff --git a/tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-3-other.stderr similarity index 70% rename from tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-64130-3-other.stderr index 1298371241ced..4bbb7731b1104 100644 --- a/tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-64130-3-other.stderr @@ -1,21 +1,21 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` - --> $DIR/issue-64130-3-other.rs:27:12 + --> $DIR/issue-64130-3-other.rs:25:12 | LL | async fn bar() { - | - within this `impl Future` + | -------------- within this `impl Future` ... LL | is_qux(bar()); | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` | note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:21:11 + --> $DIR/issue-64130-3-other.rs:18:11 | -LL | let x = Box::new(Foo); - | - has type `Box` which does not implement `Qux` +LL | let x = Foo; + | - has type `Foo` which does not implement `Qux` LL | baz().await; | ^^^^^ await occurs here, with `x` maybe used later note: required by a bound in `is_qux` - --> $DIR/issue-64130-3-other.rs:17:14 + --> $DIR/issue-64130-3-other.rs:14:14 | LL | fn is_qux(t: T) {} | ^^^ required by this bound in `is_qux` diff --git a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr deleted file mode 100644 index 884619f4dd69d..0000000000000 --- a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-64130-4-async-move.rs:20:17 - | -LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:27:31 - | -LL | match client.status() { - | ------ has type `&Client` which is not `Send` -LL | 200 => { -LL | let _x = get().await; - | ^^^^^^ await occurs here, with `client` maybe used later -... -LL | } - | - `client` is later dropped here -help: consider moving this into a `let` binding to create a shorter lived borrow - --> $DIR/issue-64130-4-async-move.rs:25:15 - | -LL | match client.status() { - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr deleted file mode 100644 index 60b7551ff8ad5..0000000000000 --- a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-64130-4-async-move.rs:21:17 - | -LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:27:23 - | -LL | match client.status() { - | ------ has type `&Client` which is not `Send` -LL | 200 => { -LL | get().await; - | ^^^^^ await occurs here, with `client` maybe used later -... -LL | } - | - `client` is later dropped here -help: consider moving this into a `let` binding to create a shorter lived borrow - --> $DIR/issue-64130-4-async-move.rs:25:15 - | -LL | match client.status() { - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-64130-4-async-move.rs b/tests/ui/async-await/issue-64130-4-async-move.rs index 5d68a808b1769..359813f637957 100644 --- a/tests/ui/async-await/issue-64130-4-async-move.rs +++ b/tests/ui/async-await/issue-64130-4-async-move.rs @@ -1,9 +1,5 @@ // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [drop_tracking_mir] check-pass -// [drop_tracking] check-pass +// check-pass use std::any::Any; use std::future::Future; @@ -19,7 +15,6 @@ impl Client { async fn get() {} pub fn foo() -> impl Future + Send { - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely let client = Client(Box::new(true)); async move { match client.status() { diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr index e044e2ca011f0..cb02fcf5ce782 100644 --- a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -12,8 +12,6 @@ LL | let g = x.lock().unwrap(); | - has type `MutexGuard<'_, u32>` which is not `Send` LL | baz().await; | ^^^^^ await occurs here, with `g` maybe used later -LL | } - | - `g` is later dropped here note: required by a bound in `is_send` --> $DIR/issue-64130-non-send-future-diags.rs:9:15 | diff --git a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr b/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr deleted file mode 100644 index fa22298658b34..0000000000000 --- a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-67252-unnamed-future.rs:21:11 - | -LL | spawn(async { - | ___________^ -LL | | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` -LL | | AFuture.await; -LL | | drop(a); -LL | | }); - | |_____^ future created by async block is not `Send` - | - = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-67252-unnamed-future.rs:23:17 - | -LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` - | - has type `*mut ()` which is not `Send` -LL | AFuture.await; - | ^^^^^ await occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `spawn` - --> $DIR/issue-67252-unnamed-future.rs:9:13 - | -LL | fn spawn(_: T) {} - | ^^^^ required by this bound in `spawn` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr b/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr deleted file mode 100644 index fa22298658b34..0000000000000 --- a/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-67252-unnamed-future.rs:21:11 - | -LL | spawn(async { - | ___________^ -LL | | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` -LL | | AFuture.await; -LL | | drop(a); -LL | | }); - | |_____^ future created by async block is not `Send` - | - = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-67252-unnamed-future.rs:23:17 - | -LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` - | - has type `*mut ()` which is not `Send` -LL | AFuture.await; - | ^^^^^ await occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `spawn` - --> $DIR/issue-67252-unnamed-future.rs:9:13 - | -LL | fn spawn(_: T) {} - | ^^^^ required by this bound in `spawn` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-67252-unnamed-future.rs b/tests/ui/async-await/issue-67252-unnamed-future.rs index bb9ad77cef31d..60717d99346ac 100644 --- a/tests/ui/async-await/issue-67252-unnamed-future.rs +++ b/tests/ui/async-await/issue-67252-unnamed-future.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 use std::future::Future; use std::pin::Pin; @@ -21,7 +18,7 @@ async fn foo() { spawn(async { //~ ERROR future cannot be sent between threads safely let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` AFuture.await; - drop(a); + let _a = a; }); } diff --git a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr similarity index 69% rename from tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-67252-unnamed-future.stderr index 8cf7bb8d9179a..069befa912162 100644 --- a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr @@ -1,19 +1,19 @@ error: future cannot be sent between threads safely - --> $DIR/issue-67252-unnamed-future.rs:21:5 + --> $DIR/issue-67252-unnamed-future.rs:18:5 | LL | spawn(async { | ^^^^^ future created by async block is not `Send` | - = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()` + = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await - --> $DIR/issue-67252-unnamed-future.rs:23:17 + --> $DIR/issue-67252-unnamed-future.rs:20:17 | LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` | - has type `*mut ()` which is not `Send` LL | AFuture.await; | ^^^^^ await occurs here, with `a` maybe used later note: required by a bound in `spawn` - --> $DIR/issue-67252-unnamed-future.rs:9:13 + --> $DIR/issue-67252-unnamed-future.rs:6:13 | LL | fn spawn(_: T) {} | ^^^^ required by this bound in `spawn` diff --git a/tests/ui/async-await/issue-68112.drop_tracking.stderr b/tests/ui/async-await/issue-68112.drop_tracking.stderr deleted file mode 100644 index bd648de30672d..0000000000000 --- a/tests/ui/async-await/issue-68112.drop_tracking.stderr +++ /dev/null @@ -1,82 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:37:18 - | -LL | require_send(send_fut); - | ^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:34:17 - | -LL | let _ = non_send_fut.await; - | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:46:18 - | -LL | require_send(send_fut); - | ^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:43:17 - | -LL | let _ = make_non_send_future1().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:65:18 - | -LL | require_send(send_fut); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this `async fn` body - --> $DIR/issue-68112.rs:50:31 - | -LL | async fn ready2(t: T) -> T { - | _______________________________^ -LL | | t -LL | | } - | |_^ -note: required because it appears within the type `impl Future>>` - --> $DIR/issue-68112.rs:53:31 - | -LL | fn make_non_send_future2() -> impl Future>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `Ready` -note: required because it's used within this `async` block - --> $DIR/issue-68112.rs:60:20 - | -LL | let send_fut = async { - | ____________________^ -LL | | let non_send_fut = make_non_send_future2(); -LL | | let _ = non_send_fut.await; -LL | | ready(0).await; -LL | | }; - | |_____^ -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr deleted file mode 100644 index 35b7341f63a4d..0000000000000 --- a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr +++ /dev/null @@ -1,82 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:37:18 - | -LL | require_send(send_fut); - | ^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:34:17 - | -LL | let _ = non_send_fut.await; - | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:46:18 - | -LL | require_send(send_fut); - | ^^^^^^^^ future created by async block is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:43:17 - | -LL | let _ = make_non_send_future1().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:65:18 - | -LL | require_send(send_fut); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this `async fn` body - --> $DIR/issue-68112.rs:50:31 - | -LL | async fn ready2(t: T) -> T { - | _______________________________^ -LL | | t -LL | | } - | |_^ -note: required because it appears within the type `impl Future>>` - --> $DIR/issue-68112.rs:53:31 - | -LL | fn make_non_send_future2() -> impl Future>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` -note: required because it's used within this `async` block - --> $DIR/issue-68112.rs:60:20 - | -LL | let send_fut = async { - | ____________________^ -LL | | let non_send_fut = make_non_send_future2(); -LL | | let _ = non_send_fut.await; -LL | | ready(0).await; -LL | | }; - | |_____^ -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-68112.rs b/tests/ui/async-await/issue-68112.rs index 19119ae0fc127..fd6089e0c03b9 100644 --- a/tests/ui/async-await/issue-68112.rs +++ b/tests/ui/async-await/issue-68112.rs @@ -1,7 +1,4 @@ // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir use std::{ cell::RefCell, diff --git a/tests/ui/async-await/issue-68112.drop_tracking_mir.stderr b/tests/ui/async-await/issue-68112.stderr similarity index 90% rename from tests/ui/async-await/issue-68112.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-68112.stderr index 7a9242cbaf591..17b619ebee32a 100644 --- a/tests/ui/async-await/issue-68112.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-68112.stderr @@ -1,5 +1,5 @@ error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:37:5 + --> $DIR/issue-68112.rs:34:5 | LL | require_send(send_fut); | ^^^^^^^^^^^^ future created by async block is not `Send` @@ -7,18 +7,18 @@ LL | require_send(send_fut); = help: the trait `Sync` is not implemented for `RefCell` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:34:17 + --> $DIR/issue-68112.rs:31:17 | LL | let _ = non_send_fut.await; | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 + --> $DIR/issue-68112.rs:11:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:46:5 + --> $DIR/issue-68112.rs:43:5 | LL | require_send(send_fut); | ^^^^^^^^^^^^ future created by async block is not `Send` @@ -26,18 +26,18 @@ LL | require_send(send_fut); = help: the trait `Sync` is not implemented for `RefCell` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:43:17 + --> $DIR/issue-68112.rs:40:17 | LL | let _ = make_non_send_future1().await; | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 + --> $DIR/issue-68112.rs:11:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:65:5 + --> $DIR/issue-68112.rs:62:5 | LL | require_send(send_fut); | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely @@ -46,7 +46,7 @@ LL | require_send(send_fut); = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this `async fn` body - --> $DIR/issue-68112.rs:50:31 + --> $DIR/issue-68112.rs:47:31 | LL | async fn ready2(t: T) -> T { | _______________________________^ @@ -54,13 +54,13 @@ LL | | t LL | | } | |_^ note: required because it appears within the type `impl Future>>` - --> $DIR/issue-68112.rs:53:31 + --> $DIR/issue-68112.rs:50:31 | LL | fn make_non_send_future2() -> impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: required because it captures the following types: `impl Future>>`, `Ready` note: required because it's used within this `async` block - --> $DIR/issue-68112.rs:60:20 + --> $DIR/issue-68112.rs:57:20 | LL | let send_fut = async { | ____________________^ @@ -70,7 +70,7 @@ LL | | ready(0).await; LL | | }; | |_____^ note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:14:25 + --> $DIR/issue-68112.rs:11:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` diff --git a/tests/ui/async-await/issue-68523-start.rs b/tests/ui/async-await/issue-68523-start.rs index 2ced88a16cc45..5adc28b203a47 100644 --- a/tests/ui/async-await/issue-68523-start.rs +++ b/tests/ui/async-await/issue-68523-start.rs @@ -4,6 +4,6 @@ #[start] pub async fn start(_: isize, _: *const *const u8) -> isize { -//~^ ERROR `start` is not allowed to be `async` +//~^ ERROR `#[start]` function is not allowed to be `async` 0 } diff --git a/tests/ui/async-await/issue-68523-start.stderr b/tests/ui/async-await/issue-68523-start.stderr index 3a0a3b5dece10..7c06fe3400ee0 100644 --- a/tests/ui/async-await/issue-68523-start.stderr +++ b/tests/ui/async-await/issue-68523-start.stderr @@ -1,8 +1,8 @@ -error[E0752]: `start` is not allowed to be `async` +error[E0752]: `#[start]` function is not allowed to be `async` --> $DIR/issue-68523-start.rs:6:1 | LL | pub async fn start(_: isize, _: *const *const u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `start` is not allowed to be `async` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `#[start]` is not allowed to be `async` error: aborting due to previous error diff --git a/tests/ui/async-await/issue-70818.drop_tracking.stderr b/tests/ui/async-await/issue-70818.drop_tracking.stderr deleted file mode 100644 index ab0698c3ec213..0000000000000 --- a/tests/ui/async-await/issue-70818.drop_tracking.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:7:38 - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | -note: captured value is not `Send` - --> $DIR/issue-70818.rs:9:18 - | -LL | async { (ty, ty1) } - | ^^^ has type `U` which is not `Send` -help: consider restricting type parameter `U` - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | +++++++++++++++++++ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-70818.no_drop_tracking.stderr b/tests/ui/async-await/issue-70818.no_drop_tracking.stderr deleted file mode 100644 index ab0698c3ec213..0000000000000 --- a/tests/ui/async-await/issue-70818.no_drop_tracking.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:7:38 - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | -note: captured value is not `Send` - --> $DIR/issue-70818.rs:9:18 - | -LL | async { (ty, ty1) } - | ^^^ has type `U` which is not `Send` -help: consider restricting type parameter `U` - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | +++++++++++++++++++ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index 2941de0f57714..019c56eb2fa3e 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 use std::future::Future; diff --git a/tests/ui/async-await/issue-70818.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70818.stderr similarity index 90% rename from tests/ui/async-await/issue-70818.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-70818.stderr index ab0698c3ec213..20109d4d1166a 100644 --- a/tests/ui/async-await/issue-70818.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,11 +1,11 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:7:38 + --> $DIR/issue-70818.rs:4:38 | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | note: captured value is not `Send` - --> $DIR/issue-70818.rs:9:18 + --> $DIR/issue-70818.rs:6:18 | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr deleted file mode 100644 index f80bb4242aa70..0000000000000 --- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ /dev/null @@ -1,41 +0,0 @@ -error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:18:23 - | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely - | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` -note: required because it appears within the type `PhantomData<*mut ()>` - --> $SRC_DIR/core/src/marker.rs:LL:COL -note: required because it appears within the type `NotSync` - --> $DIR/issue-70935-complex-spans.rs:12:8 - | -LL | struct NotSync(PhantomData<*mut ()>); - | ^^^^^^^ - = note: required for `&NotSync` to implement `Send` -note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:22:13 - | -LL | baz(|| async { - | ^^ -note: required because it's used within this `async fn` body - --> $DIR/issue-70935-complex-spans.rs:15:67 - | -LL | async fn baz(_c: impl FnMut() -> T) where T: Future { - | ___________________________________________________________________^ -LL | | } - | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` -note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:21:5 - | -LL | / async move { -LL | | baz(|| async { -LL | | foo(x.clone()); -LL | | }).await; -LL | | } - | |_____^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr deleted file mode 100644 index d8ef6a5eedb7d..0000000000000 --- a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:18:23 - | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-70935-complex-spans.rs:24:12 - | -LL | baz(|| async { - | _____________- -LL | | foo(x.clone()); -LL | | }).await; - | | - ^^^^^- the value is later dropped here - | | | | - | |_________| await occurs here, with the value maybe used later - | has type `[closure@$DIR/issue-70935-complex-spans.rs:22:13: 22:15]` which is not `Send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 9ebde1d397733..4af73739584cb 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -1,7 +1,4 @@ // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // #70935: Check if we do not emit snippet // with newlines which lead complex diagnostics. @@ -16,8 +13,7 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { } fn foo(x: NotSync) -> impl Future + Send { - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely - //[drop_tracking,drop_tracking_mir]~^^ ERROR `*mut ()` cannot be shared between threads + //~^ ERROR `*mut ()` cannot be shared between threads safely async move { baz(|| async { foo(x.clone()); diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr similarity index 85% rename from tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr rename to tests/ui/async-await/issue-70935-complex-spans.stderr index eb9d93e229fb5..ab834daa85dc2 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -1,5 +1,5 @@ error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:18:23 + --> $DIR/issue-70935-complex-spans.rs:15:23 | LL | fn foo(x: NotSync) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely @@ -8,18 +8,18 @@ LL | fn foo(x: NotSync) -> impl Future + Send { note: required because it appears within the type `PhantomData<*mut ()>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `NotSync` - --> $DIR/issue-70935-complex-spans.rs:12:8 + --> $DIR/issue-70935-complex-spans.rs:9:8 | LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:22:13 + --> $DIR/issue-70935-complex-spans.rs:18:13 | LL | baz(|| async { | ^^ note: required because it's used within this `async fn` body - --> $DIR/issue-70935-complex-spans.rs:15:67 + --> $DIR/issue-70935-complex-spans.rs:12:67 | LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ @@ -27,7 +27,7 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:21:5 + --> $DIR/issue-70935-complex-spans.rs:17:5 | LL | / async move { LL | | baz(|| async { diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr index a344246d6bfff..443af010c4a1a 100644 --- a/tests/ui/async-await/issue-71137.stderr +++ b/tests/ui/async-await/issue-71137.stderr @@ -12,9 +12,6 @@ LL | let mut guard = m.lock().unwrap(); | --------- has type `MutexGuard<'_, i32>` which is not `Send` LL | (async { "right"; }).await; | ^^^^^ await occurs here, with `mut guard` maybe used later -LL | *guard += 1; -LL | } - | - `mut guard` is later dropped here note: required by a bound in `fake_spawn` --> $DIR/issue-71137.rs:8:27 | diff --git a/tests/ui/async-await/issue-73137.rs b/tests/ui/async-await/issue-73137.rs index dcbe7765a9e1c..c43ce2cadba04 100644 --- a/tests/ui/async-await/issue-73137.rs +++ b/tests/ui/async-await/issue-73137.rs @@ -2,9 +2,6 @@ // run-pass // edition:2018 -// revisions: normal drop-tracking -// [normal]compile-flags: -Zdrop-tracking=no -// [drop-tracking]compile-flags: -Zdrop-tracking #![allow(dead_code)] use std::future::Future; diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr deleted file mode 100644 index 6d19c3beb2fe1..0000000000000 --- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7 - | -LL | 1 = 2; - | - ^ - | | - | cannot assign to this expression - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr deleted file mode 100644 index 6d19c3beb2fe1..0000000000000 --- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7 - | -LL | 1 = 2; - | - ^ - | | - | cannot assign to this expression - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr deleted file mode 100644 index 6d19c3beb2fe1..0000000000000 --- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7 - | -LL | 1 = 2; - | - ^ - | | - | cannot assign to this expression - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs deleted file mode 100644 index 1fa8d69143a22..0000000000000 --- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs +++ /dev/null @@ -1,17 +0,0 @@ -// edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// -// Regression test for issue #73741 -// Ensures that we don't emit spurious errors when -// a type error ocurrs in an `async fn` - -async fn weird() { - 1 = 2; //~ ERROR invalid left-hand side - - let mut loop_count = 0; - async {}.await -} - -fn main() {} diff --git a/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr b/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr deleted file mode 100644 index adb7b9bf4bf8d..0000000000000 --- a/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-86507.rs:20:13 - | -LL | / Box::pin( -LL | | async move { -LL | | let x = x; -LL | | } -LL | | ) - | |_____________^ future created by async block is not `Send` - | -note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> $DIR/issue-86507.rs:22:29 - | -LL | let x = x; - | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` -help: consider further restricting this bound - | -LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) - | +++++++++++++++++++ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-86507.no_drop_tracking.stderr b/tests/ui/async-await/issue-86507.no_drop_tracking.stderr deleted file mode 100644 index adb7b9bf4bf8d..0000000000000 --- a/tests/ui/async-await/issue-86507.no_drop_tracking.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-86507.rs:20:13 - | -LL | / Box::pin( -LL | | async move { -LL | | let x = x; -LL | | } -LL | | ) - | |_____________^ future created by async block is not `Send` - | -note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> $DIR/issue-86507.rs:22:29 - | -LL | let x = x; - | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` -help: consider further restricting this bound - | -LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) - | +++++++++++++++++++ - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issue-86507.rs b/tests/ui/async-await/issue-86507.rs index 63c298dbe3dcb..317f0317664b6 100644 --- a/tests/ui/async-await/issue-86507.rs +++ b/tests/ui/async-await/issue-86507.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 use ::core::pin::Pin; diff --git a/tests/ui/async-await/issue-86507.drop_tracking.stderr b/tests/ui/async-await/issue-86507.stderr similarity index 80% rename from tests/ui/async-await/issue-86507.drop_tracking.stderr rename to tests/ui/async-await/issue-86507.stderr index adb7b9bf4bf8d..d5a3f72cf251f 100644 --- a/tests/ui/async-await/issue-86507.drop_tracking.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -1,5 +1,5 @@ error: future cannot be sent between threads safely - --> $DIR/issue-86507.rs:20:13 + --> $DIR/issue-86507.rs:17:13 | LL | / Box::pin( LL | | async move { @@ -9,11 +9,11 @@ LL | | ) | |_____________^ future created by async block is not `Send` | note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> $DIR/issue-86507.rs:22:29 + --> $DIR/issue-86507.rs:19:29 | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` + = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` help: consider further restricting this bound | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/tests/ui/async-await/issue-93197.rs b/tests/ui/async-await/issue-93197.rs index c627fe17afbbe..05ec013d0afd8 100644 --- a/tests/ui/async-await/issue-93197.rs +++ b/tests/ui/async-await/issue-93197.rs @@ -1,7 +1,6 @@ // Regression test for #93197 // check-pass // edition:2021 -// compile-flags: -Zdrop-tracking #![feature(try_blocks)] diff --git a/tests/ui/async-await/issue-93648.rs b/tests/ui/async-await/issue-93648.rs index ec2249ca592b5..b27a79a428bd6 100644 --- a/tests/ui/async-await/issue-93648.rs +++ b/tests/ui/async-await/issue-93648.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2021 // build-pass diff --git a/tests/ui/async-await/issues/auxiliary/issue_67893.rs b/tests/ui/async-await/issues/auxiliary/issue_67893.rs index d5394469806da..efde4d2864d13 100644 --- a/tests/ui/async-await/issues/auxiliary/issue_67893.rs +++ b/tests/ui/async-await/issues/auxiliary/issue_67893.rs @@ -1,13 +1,12 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 use std::sync::{Arc, Mutex}; +fn make_arc() -> Arc> { unimplemented!() } + pub async fn f(_: ()) {} pub async fn run() { - let x: Arc> = unimplemented!(); + let x: Arc> = make_arc(); f(*x.lock().unwrap()).await; } diff --git a/tests/ui/async-await/issues/issue-107280.rs b/tests/ui/async-await/issues/issue-107280.rs index 85fce87403a9b..81ae9553cf01e 100644 --- a/tests/ui/async-await/issues/issue-107280.rs +++ b/tests/ui/async-await/issues/issue-107280.rs @@ -3,11 +3,6 @@ async fn foo() { inner::().await //~^ ERROR: function takes 2 generic arguments but 1 generic argument was supplied - //~| ERROR: type inside `async fn` body must be known in this context - //~| ERROR: type inside `async fn` body must be known in this context - //~| ERROR: type inside `async fn` body must be known in this context - //~| ERROR: type inside `async fn` body must be known in this context - //~| ERROR: type inside `async fn` body must be known in this context } async fn inner() {} diff --git a/tests/ui/async-await/issues/issue-107280.stderr b/tests/ui/async-await/issues/issue-107280.stderr index 2e69862a0e09f..c5fd5c5bf0a03 100644 --- a/tests/ui/async-await/issues/issue-107280.stderr +++ b/tests/ui/async-await/issues/issue-107280.stderr @@ -7,7 +7,7 @@ LL | inner::().await | expected 2 generic arguments | note: function defined here, with 2 generic parameters: `T`, `PING` - --> $DIR/issue-107280.rs:13:10 + --> $DIR/issue-107280.rs:8:10 | LL | async fn inner() {} | ^^^^^ - ---------------- @@ -16,67 +16,6 @@ help: add missing generic argument LL | inner::().await | ++++++ -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/issue-107280.rs:4:5 - | -LL | inner::().await - | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/issue-107280.rs:4:22 - | -LL | inner::().await - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/issue-107280.rs:4:5 - | -LL | inner::().await - | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/issue-107280.rs:4:22 - | -LL | inner::().await - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/issue-107280.rs:4:5 - | -LL | inner::().await - | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/issue-107280.rs:4:22 - | -LL | inner::().await - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/issue-107280.rs:4:5 - | -LL | inner::().await - | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/issue-107280.rs:4:22 - | -LL | inner::().await - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/issue-107280.rs:4:5 - | -LL | inner::().await - | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/issue-107280.rs:4:22 - | -LL | inner::().await - | ^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0107, E0698. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr index 53d0577a1b23c..bb617d09076f0 100644 --- a/tests/ui/async-await/issues/issue-62009-1.stderr +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -24,18 +24,18 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^ only allowed inside `async` functions and blocks -error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future +error[E0277]: `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future --> $DIR/issue-62009-1.rs:12:16 | LL | (|_| 2333).await; | -^^^^^ | || - | |`[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future + | |`{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` - = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited - = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture` + = help: the trait `Future` is not implemented for closure `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` + = note: {closure@$DIR/issue-62009-1.rs:12:6: 12:9} must be a future or must implement `IntoFuture` to be awaited + = note: required for `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` to implement `IntoFuture` error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr deleted file mode 100644 index 53d32620241c7..0000000000000 --- a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-65436-raw-ptr-not-send.rs:17:17 - | -LL | assert_send(async { - | _________________^ -LL | | -LL | | bar(Foo(std::ptr::null())).await; -LL | | }) - | |_____^ future created by async block is not `Send` - | - = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:17:17: 20:6]`, the trait `Send` is not implemented for `*const u8` -note: future is not `Send` as this value is used across an await - --> $DIR/issue-65436-raw-ptr-not-send.rs:19:36 - | -LL | bar(Foo(std::ptr::null())).await; - | ---------------- ^^^^^- `std::ptr::null()` is later dropped here - | | | - | | await occurs here, with `std::ptr::null()` maybe used later - | has type `*const u8` which is not `Send` -help: consider moving this into a `let` binding to create a shorter lived borrow - --> $DIR/issue-65436-raw-ptr-not-send.rs:19:13 - | -LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `assert_send` - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs index d7ef929517c74..ef6f105f34abb 100644 --- a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs +++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs @@ -1,9 +1,5 @@ // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [drop_tracking] check-pass -// [drop_tracking_mir] check-pass +// check-pass struct Foo(*const u8); @@ -15,7 +11,6 @@ fn assert_send(_: T) {} fn main() { assert_send(async { - //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely bar(Foo(std::ptr::null())).await; }) } diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs index 80d824d3b2ee6..caed762691e4d 100644 --- a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs +++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs @@ -1,10 +1,6 @@ // build-pass // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - #![feature(if_let_guard)] static mut A: [i32; 5] = [1, 2, 3, 4, 5]; diff --git a/tests/ui/async-await/issues/issue-67893.rs b/tests/ui/async-await/issues/issue-67893.rs index d73772e5fa0d9..359c75f170c39 100644 --- a/tests/ui/async-await/issues/issue-67893.rs +++ b/tests/ui/async-await/issues/issue-67893.rs @@ -7,5 +7,5 @@ fn g(_: impl Send) {} fn main() { g(issue_67893::run()) - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR `MutexGuard<'_, ()>` cannot be sent between threads safely } diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr index c941b9eeb29ac..3d6d1fb5c0919 100644 --- a/tests/ui/async-await/issues/issue-67893.stderr +++ b/tests/ui/async-await/issues/issue-67893.stderr @@ -1,18 +1,27 @@ -error: future cannot be sent between threads safely +error[E0277]: `MutexGuard<'_, ()>` cannot be sent between threads safely --> $DIR/issue-67893.rs:9:7 | LL | g(issue_67893::run()) - | ^^^^^^^^^^^^^^^^^^ future is not `Send` + | - ^^^^^^^^^^^^^^^^^^ `MutexGuard<'_, ()>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + ::: $DIR/auxiliary/issue_67893.rs:9:1 + | +LL | pub async fn run() { + | ------------------ within this `impl Future` | = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` -note: future is not `Send` as this value is used across an await - --> $DIR/auxiliary/issue_67893.rs:12:27 + = note: required because it captures the following types: `Arc>`, `MutexGuard<'_, ()>`, `impl Future` +note: required because it's used within this `async fn` body + --> $DIR/auxiliary/issue_67893.rs:9:20 | -LL | f(*x.lock().unwrap()).await; - | ----------------- ^^^^^- `x.lock().unwrap()` is later dropped here - | | | - | | await occurs here, with `x.lock().unwrap()` maybe used later - | has type `MutexGuard<'_, ()>` which is not `Send` +LL | pub async fn run() { + | ____________________^ +LL | | let x: Arc> = make_arc(); +LL | | f(*x.lock().unwrap()).await; +LL | | } + | |_^ note: required by a bound in `g` --> $DIR/issue-67893.rs:6:14 | @@ -21,3 +30,4 @@ LL | fn g(_: impl Send) {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issues/issue-78600.rs b/tests/ui/async-await/issues/issue-78600.rs index 8aaeaecf3e1da..4303fc7952f2b 100644 --- a/tests/ui/async-await/issues/issue-78600.rs +++ b/tests/ui/async-await/issues/issue-78600.rs @@ -1,10 +1,10 @@ +// check-pass // edition:2018 struct S<'a>(&'a i32); impl<'a> S<'a> { async fn new(i: &'a i32) -> Result { - //~^ ERROR: `async fn` Ok(S(&22)) } } diff --git a/tests/ui/async-await/issues/issue-78600.stderr b/tests/ui/async-await/issues/issue-78600.stderr deleted file mode 100644 index 37eafa996c535..0000000000000 --- a/tests/ui/async-await/issues/issue-78600.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-78600.rs:6:33 - | -LL | async fn new(i: &'a i32) -> Result { - | ^^^^^^^----^^^^^ - | | - | help: consider spelling out the type instead: `S<'a>` - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/large_moves.attribute.stderr b/tests/ui/async-await/large_moves.attribute.stderr deleted file mode 100644 index 1d1999462cedd..0000000000000 --- a/tests/ui/async-await/large_moves.attribute.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: moving 10024 bytes - --> $DIR/large_moves.rs:21:14 - | -LL | let z = (x, 42); - | ^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` -note: the lint level is defined here - --> $DIR/large_moves.rs:1:9 - | -LL | #![deny(large_assignments)] - | ^^^^^^^^^^^^^^^^^ - -error: moving 10024 bytes - --> $DIR/large_moves.rs:22:13 - | -LL | let a = z.0; - | ^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: moving 9999 bytes - --> $DIR/large_moves.rs:27:13 - | -LL | let _ = NotBox::new([0; 9999]); - | ^^^^^^^^^^^^^^^^^^^^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: moving 9999 bytes - --> $DIR/large_moves.rs:41:13 - | -LL | data, - | ^^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/large_moves.option.stderr b/tests/ui/async-await/large_moves.option.stderr deleted file mode 100644 index 1d1999462cedd..0000000000000 --- a/tests/ui/async-await/large_moves.option.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: moving 10024 bytes - --> $DIR/large_moves.rs:21:14 - | -LL | let z = (x, 42); - | ^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` -note: the lint level is defined here - --> $DIR/large_moves.rs:1:9 - | -LL | #![deny(large_assignments)] - | ^^^^^^^^^^^^^^^^^ - -error: moving 10024 bytes - --> $DIR/large_moves.rs:22:13 - | -LL | let a = z.0; - | ^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: moving 9999 bytes - --> $DIR/large_moves.rs:27:13 - | -LL | let _ = NotBox::new([0; 9999]); - | ^^^^^^^^^^^^^^^^^^^^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: moving 9999 bytes - --> $DIR/large_moves.rs:41:13 - | -LL | data, - | ^^^^ value moved from here - | - = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr deleted file mode 100644 index 8a7317bb95a70..0000000000000 --- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 - | -LL | async fn rec_1() { - | ^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18 - | -LL | async fn rec_2() { - | ^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr deleted file mode 100644 index 8a7317bb95a70..0000000000000 --- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 - | -LL | async fn rec_1() { - | ^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18 - | -LL | async fn rec_2() { - | ^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs index a241f30e73e6e..bb2a61f03ce1f 100644 --- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs +++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - // edition:2018 // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr similarity index 75% rename from tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr rename to tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr index 8a7317bb95a70..9442609e80586 100644 --- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr +++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr @@ -1,17 +1,17 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 + --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:1 | LL | async fn rec_1() { - | ^ recursive `async fn` + | ^^^^^^^^^^^^^^^^ recursive `async fn` | = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18 + --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:1 | LL | async fn rec_2() { - | ^ recursive `async fn` + | ^^^^^^^^^^^^^^^^ recursive `async fn` | = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs index 258da0756de31..3fed7c972a1a0 100644 --- a/tests/ui/async-await/non-trivial-drop.rs +++ b/tests/ui/async-await/non-trivial-drop.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // build-pass // edition:2018 diff --git a/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr deleted file mode 100644 index 34d8a159f1064..0000000000000 --- a/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0277]: `NotSend` cannot be sent between threads safely - --> $DIR/partial-drop-partial-reinit.rs:9:16 - | -LL | gimme_send(foo()); - | ---------- ^^^^^ `NotSend` cannot be sent between threads safely - | | - | required by a bound introduced by this call -... -LL | async fn foo() { - | - within this `impl Future` - | - = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` - = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` -note: required because it's used within this `async fn` body - --> $DIR/partial-drop-partial-reinit.rs:31:16 - | -LL | async fn foo() { - | ________________^ -LL | | -LL | | -LL | | let mut x = (NotSend {},); -... | -LL | | bar().await; -LL | | } - | |_^ -note: required by a bound in `gimme_send` - --> $DIR/partial-drop-partial-reinit.rs:17:18 - | -LL | fn gimme_send(t: T) { - | ^^^^ required by this bound in `gimme_send` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/partial-drop-partial-reinit.rs b/tests/ui/async-await/partial-drop-partial-reinit.rs index 7d097e72fb49d..75acb442e7a33 100644 --- a/tests/ui/async-await/partial-drop-partial-reinit.rs +++ b/tests/ui/async-await/partial-drop-partial-reinit.rs @@ -1,7 +1,4 @@ // edition:2021 -// revisions: no_drop_tracking drop_tracking -// [drop_tracking] compile-flags: -Zdrop-tracking=yes -// [no_drop_tracking] compile-flags: -Zdrop-tracking=no #![feature(negative_impls)] #![allow(unused)] diff --git a/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr similarity index 73% rename from tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr rename to tests/ui/async-await/partial-drop-partial-reinit.stderr index 17b4ef7bdc671..d115c1b1cc4bd 100644 --- a/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr +++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr @@ -1,5 +1,5 @@ error[E0277]: `NotSend` cannot be sent between threads safely - --> $DIR/partial-drop-partial-reinit.rs:9:16 + --> $DIR/partial-drop-partial-reinit.rs:6:16 | LL | gimme_send(foo()); | ---------- ^^^^^ `NotSend` cannot be sent between threads safely @@ -7,13 +7,13 @@ LL | gimme_send(foo()); | required by a bound introduced by this call ... LL | async fn foo() { - | - within this `impl Future` + | -------------- within this `impl Future` | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future` + = note: required because it captures the following types: `(NotSend,)`, `impl Future` note: required because it's used within this `async fn` body - --> $DIR/partial-drop-partial-reinit.rs:31:16 + --> $DIR/partial-drop-partial-reinit.rs:28:16 | LL | async fn foo() { | ________________^ @@ -25,7 +25,7 @@ LL | | bar().await; LL | | } | |_^ note: required by a bound in `gimme_send` - --> $DIR/partial-drop-partial-reinit.rs:17:18 + --> $DIR/partial-drop-partial-reinit.rs:14:18 | LL | fn gimme_send(t: T) { | ^^^^ required by this bound in `gimme_send` diff --git a/tests/ui/async-await/pin-needed-to-poll.stderr b/tests/ui/async-await/pin-needed-to-poll.stderr index b1f4a73aafeab..964709daeda2d 100644 --- a/tests/ui/async-await/pin-needed-to-poll.stderr +++ b/tests/ui/async-await/pin-needed-to-poll.stderr @@ -6,14 +6,12 @@ LL | struct Sleep; ... LL | self.sleep.poll(cx) | ^^^^ method not found in `Sleep` - --> $SRC_DIR/core/src/future/future.rs:LL:COL | - = note: the method is available for `Pin<&mut Sleep>` here +help: consider pinning the expression | -help: consider wrapping the receiver expression with the appropriate type +LL ~ let mut pinned = std::pin::pin!(self.sleep); +LL ~ pinned.as_mut().poll(cx) | -LL | Pin::new(&mut self.sleep).poll(cx) - | +++++++++++++ + error: aborting due to previous error diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr deleted file mode 100644 index 7e63a8da55255..0000000000000 --- a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/recursive-async-impl-trait-type.rs:8:40 - | -LL | async fn recursive_async_function() -> () { - | ^^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr deleted file mode 100644 index 7e63a8da55255..0000000000000 --- a/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/recursive-async-impl-trait-type.rs:8:40 - | -LL | async fn recursive_async_function() -> () { - | ^^ recursive `async fn` - | - = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` - = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.rs b/tests/ui/async-await/recursive-async-impl-trait-type.rs index 60b34d3a17415..edc4cb8ac5df3 100644 --- a/tests/ui/async-await/recursive-async-impl-trait-type.rs +++ b/tests/ui/async-await/recursive-async-impl-trait-type.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr similarity index 77% rename from tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr rename to tests/ui/async-await/recursive-async-impl-trait-type.stderr index 7e63a8da55255..64917329c499f 100644 --- a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr +++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr @@ -1,8 +1,8 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/recursive-async-impl-trait-type.rs:8:40 + --> $DIR/recursive-async-impl-trait-type.rs:5:1 | LL | async fn recursive_async_function() -> () { - | ^^ recursive `async fn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn` | = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr index 1b847b59eb5b9..77385e966ce2f 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr @@ -7,7 +7,7 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { @@ -16,11 +16,17 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:37:17 + | +LL | F: Future + Send + 'static, + | ^^^^ -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { @@ -29,9 +35,16 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other + | + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:37:17 | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` +LL | F: Future + Send + 'static, + | ^^^^ error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr index 1b847b59eb5b9..77385e966ce2f 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr @@ -7,7 +7,7 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { @@ -16,11 +16,17 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:37:17 + | +LL | F: Future + Send + 'static, + | ^^^^ -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { @@ -29,9 +35,16 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other + | + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:37:17 | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` +LL | F: Future + Send + 'static, + | ^^^^ error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr index 33e22dec3f7b2..98e3cbd0d7f41 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr @@ -7,7 +7,7 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:15:5 | LL | / spawn(async move { @@ -16,11 +16,17 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:35:17 + | +LL | F: Future + Send + 'static, + | ^^^^ -error: higher-ranked lifetime error +error[E0308]: mismatched types --> $DIR/issue-110963-early.rs:15:5 | LL | / spawn(async move { @@ -29,9 +35,17 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ + | |______^ one type is more general than the other + | + = note: expected trait `Send` + found trait `for<'a> Send` +note: the lifetime requirement is introduced here + --> $DIR/issue-110963-early.rs:35:17 | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` +LL | F: Future + Send + 'static, + | ^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr b/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr deleted file mode 100644 index 6b4a3a36395f8..0000000000000 --- a/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0698`. diff --git a/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr b/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr deleted file mode 100644 index 6642e90acd861..0000000000000 --- a/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/unresolved_type_param.rs:12:5 - | -LL | bar().await; - | ^^^ cannot infer type for type parameter `T` declared on the function `bar` - | -note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:12:11 - | -LL | bar().await; - | ^^^^^ - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0698`. diff --git a/tests/ui/async-await/unresolved_type_param.rs b/tests/ui/async-await/unresolved_type_param.rs index ca0a92b943473..dd5aa0dd077ae 100644 --- a/tests/ui/async-await/unresolved_type_param.rs +++ b/tests/ui/async-await/unresolved_type_param.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // Provoke an unresolved type error (T). // Error message should pinpoint the type parameter T as needing to be bound // (rather than give a general error message) @@ -10,27 +7,6 @@ async fn bar() -> () {} async fn foo() { bar().await; - //[drop_tracking_mir]~^ ERROR type annotations needed - //[drop_tracking_mir]~| NOTE cannot infer type of the type parameter `T` - //[no_drop_tracking,drop_tracking]~^^^ ERROR type inside `async fn` body must be known in this context - //[no_drop_tracking,drop_tracking]~| ERROR type inside `async fn` body must be known in this context - //[no_drop_tracking,drop_tracking]~| ERROR type inside `async fn` body must be known in this context - //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T` - //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T` - //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T` - //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await` - //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await` - //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await` - //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await` - //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await` - //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await` - //[no_drop_tracking]~^^^^^^^^^^^^^^^ ERROR type inside `async fn` body must be known in this context - //[no_drop_tracking]~| ERROR type inside `async fn` body must be known in this context - //[no_drop_tracking]~| NOTE cannot infer type for type parameter `T` - //[no_drop_tracking]~| NOTE cannot infer type for type parameter `T` - //[no_drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await` - //[no_drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await` - //[no_drop_tracking]~| NOTE in this expansion of desugaring of `await` - //[no_drop_tracking]~| NOTE in this expansion of desugaring of `await` + //~^ ERROR type annotations needed } fn main() {} diff --git a/tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr b/tests/ui/async-await/unresolved_type_param.stderr similarity index 89% rename from tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr rename to tests/ui/async-await/unresolved_type_param.stderr index 95c799468314f..45aa766065e46 100644 --- a/tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr +++ b/tests/ui/async-await/unresolved_type_param.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/unresolved_type_param.rs:12:5 + --> $DIR/unresolved_type_param.rs:9:5 | LL | bar().await; | ^^^ cannot infer type of the type parameter `T` declared on the function `bar` diff --git a/tests/ui/async-await/unsized-across-await.rs b/tests/ui/async-await/unsized-across-await.rs new file mode 100644 index 0000000000000..32cb4f88eaef6 --- /dev/null +++ b/tests/ui/async-await/unsized-across-await.rs @@ -0,0 +1,16 @@ +// edition: 2021 + +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete + +async fn f() {} + +async fn g(x: Box) { + let _x = *x; + //~^ ERROR the size for values of type `dyn std::fmt::Display` cannot be known at compilation time + f().await; +} + +fn main() { + let _a = g(Box::new(5)); +} diff --git a/tests/ui/async-await/unsized-across-await.stderr b/tests/ui/async-await/unsized-across-await.stderr new file mode 100644 index 0000000000000..649b12ce5a5bb --- /dev/null +++ b/tests/ui/async-await/unsized-across-await.stderr @@ -0,0 +1,21 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unsized-across-await.rs:3:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `dyn std::fmt::Display` cannot be known at compilation time + --> $DIR/unsized-across-await.rs:9:9 + | +LL | let _x = *x; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn std::fmt::Display` + = note: all values live across `await` must have a statically known size + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/pre-cfg.rs b/tests/ui/auto-traits/pre-cfg.rs new file mode 100644 index 0000000000000..e6e840dcbab6f --- /dev/null +++ b/tests/ui/auto-traits/pre-cfg.rs @@ -0,0 +1,8 @@ +// check-pass + +#[cfg(FALSE)] +auto trait Foo {} +//~^ WARN `auto` traits are unstable +//~| WARN unstable syntax can change at any point in the future, causing a hard error! + +fn main() {} diff --git a/tests/ui/auto-traits/pre-cfg.stderr b/tests/ui/auto-traits/pre-cfg.stderr new file mode 100644 index 0000000000000..6efa05b4326d5 --- /dev/null +++ b/tests/ui/auto-traits/pre-cfg.stderr @@ -0,0 +1,13 @@ +warning: `auto` traits are unstable + --> $DIR/pre-cfg.rs:4:1 + | +LL | auto trait Foo {} + | ^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 1 warning emitted + diff --git a/tests/ui/block-result/block-must-not-have-result-res.stderr b/tests/ui/block-result/block-must-not-have-result-res.stderr index 0080d06dd207a..b7427462bcbd5 100644 --- a/tests/ui/block-result/block-must-not-have-result-res.stderr +++ b/tests/ui/block-result/block-must-not-have-result-res.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/block-must-not-have-result-res.rs:5:9 | LL | fn drop(&mut self) { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | true | ^^^^ expected `()`, found `bool` diff --git a/tests/ui/block-result/issue-20862.stderr b/tests/ui/block-result/issue-20862.stderr index 37bad64c5bf68..1df3a6836206b 100644 --- a/tests/ui/block-result/issue-20862.stderr +++ b/tests/ui/block-result/issue-20862.stderr @@ -2,12 +2,12 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:2:5 | LL | fn foo(x: i32) { - | - help: a return type might be missing here: `-> _` + | - help: a return type might be missing here: `-> _` LL | |y| x + y | ^^^^^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-20862.rs:2:5: 2:8]` + found closure `{closure@$DIR/issue-20862.rs:2:5: 2:8}` error[E0618]: expected function, found `()` --> $DIR/issue-20862.rs:7:13 diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr index 677b40aaa9dad..1064848f5139e 100644 --- a/tests/ui/block-result/issue-22645.stderr +++ b/tests/ui/block-result/issue-22645.stderr @@ -17,7 +17,7 @@ error[E0308]: mismatched types --> $DIR/issue-22645.rs:15:3 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | let b = Bob + 3.5; LL | b + 3 | ^^^^^ expected `()`, found `Bob` diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr index 8cd4bd65871a3..417991e9e0bbd 100644 --- a/tests/ui/block-result/issue-5500.stderr +++ b/tests/ui/block-result/issue-5500.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:2:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | &panic!() | ^^^^^^^^^ expected `()`, found `&_` | diff --git a/tests/ui/borrowck/async-reference-generality.rs b/tests/ui/borrowck/async-reference-generality.rs index 487d1ac81bfc6..668df9ea7101d 100644 --- a/tests/ui/borrowck/async-reference-generality.rs +++ b/tests/ui/borrowck/async-reference-generality.rs @@ -1,5 +1,4 @@ -// check-fail -// known-bug: #99492 +// check-pass // edition: 2021 use std::marker::PhantomData; diff --git a/tests/ui/borrowck/async-reference-generality.stderr b/tests/ui/borrowck/async-reference-generality.stderr deleted file mode 100644 index af720ad29314f..0000000000000 --- a/tests/ui/borrowck/async-reference-generality.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/async-reference-generality.rs:23:5 - | -LL | / async { -LL | | let _x = Struct::, _>(PhantomData); -LL | | async {}.await; -LL | | } - | |_____^ one type is more general than the other - | - = note: expected reference `&()` - found reference `&()` - -error[E0308]: mismatched types - --> $DIR/async-reference-generality.rs:23:5 - | -LL | / async { -LL | | let _x = Struct::, _>(PhantomData); -LL | | async {}.await; -LL | | } - | |_____^ one type is more general than the other - | - = note: expected reference `&()` - found reference `&()` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs deleted file mode 100644 index addbe5d658aee..0000000000000 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs +++ /dev/null @@ -1,23 +0,0 @@ -// compile-flags: -Zdrop-tracking-mir -// edition:2021 - -use std::future::Future; - -trait Client { - type Connecting<'a>: Future + Send - where - Self: 'a; - - fn connect(&'_ self) -> Self::Connecting<'a>; - //~^ ERROR use of undeclared lifetime name `'a` -} - -fn call_connect(c: &'_ C) -> impl '_ + Future + Send -where - C: Client + Send + Sync, -{ - async move { c.connect().await } - //~^ ERROR `C` does not live long enough -} - -fn main() {} diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr deleted file mode 100644 index 53abe3dc9521d..0000000000000 --- a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/erase-error-in-mir-drop-tracking.rs:11:46 - | -LL | fn connect(&'_ self) -> Self::Connecting<'a>; - | ^^ undeclared lifetime - | -help: consider introducing lifetime `'a` here - | -LL | fn connect<'a>(&'_ self) -> Self::Connecting<'a>; - | ++++ -help: consider introducing lifetime `'a` here - | -LL | trait Client<'a> { - | ++++ - -error: `C` does not live long enough - --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5 - | -LL | async move { c.connect().await } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr index f0b5748463261..3debfb62c3f9c 100644 --- a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr +++ b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let _action = move || { | ------- | | | - | | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:11]` contains a lifetime `'2` + | | return type of closure `{closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:11}` contains a lifetime `'2` | lifetime `'1` represents this closure's body LL | || f() // The `nested` closure | ^^^^^^ returning this value requires that `'1` must outlive `'2` diff --git a/tests/ui/borrowck/issue-81899.stderr b/tests/ui/borrowck/issue-81899.stderr index 63e817239c64e..5ff33933cf095 100644 --- a/tests/ui/borrowck/issue-81899.stderr +++ b/tests/ui/borrowck/issue-81899.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | panic!() | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5 | -note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` +note: inside `f::<{closure@$DIR/issue-81899.rs:4:31: 4:34}>` --> $DIR/issue-81899.rs:11:5 | LL | panic!() diff --git a/tests/ui/borrowck/issue-88434-minimal-example.stderr b/tests/ui/borrowck/issue-88434-minimal-example.stderr index 4c887b2ad42c3..7b785b25bd054 100644 --- a/tests/ui/borrowck/issue-88434-minimal-example.stderr +++ b/tests/ui/borrowck/issue-88434-minimal-example.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | panic!() | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5 | -note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` +note: inside `f::<{closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28}>` --> $DIR/issue-88434-minimal-example.rs:10:5 | LL | panic!() diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index f7257817a8b2e..9732b8cfa4dad 100644 --- a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | panic!() | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5 | -note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` +note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34}>` --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5 | LL | panic!() diff --git a/tests/ui/borrowck/issue-92157.rs b/tests/ui/borrowck/issue-92157.rs index 6ee2320a603ad..3a6f8908b219f 100644 --- a/tests/ui/borrowck/issue-92157.rs +++ b/tests/ui/borrowck/issue-92157.rs @@ -9,7 +9,7 @@ extern {} #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { - //~^ ERROR: incorrect number of parameters for the `start` lang item + //~^ ERROR lang item `start` function has wrong type [E0308] 40+2 } diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr index a4010d73d057a..a46b1288911dc 100644 --- a/tests/ui/borrowck/issue-92157.stderr +++ b/tests/ui/borrowck/issue-92157.stderr @@ -1,11 +1,12 @@ -error: incorrect number of parameters for the `start` lang item +error[E0308]: lang item `start` function has wrong type --> $DIR/issue-92157.rs:11:1 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: the `start` lang item should have four parameters, but found 3 - = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` + found signature `fn(fn() -> T, isize, *const *const u8) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr index 776c338deacf4..d7762621cc5c7 100644 --- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr @@ -24,7 +24,7 @@ error: lifetime may not live long enough LL | move |()| s.chars().map(|c| format!("{}{}", c, s)) | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2` + | | return type of closure `Map, {closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32}>` contains a lifetime `'2` | lifetime `'1` represents this closure's body | = note: closure implements `Fn`, so references to captured variables can't escape the closure diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 930fea9158d45..7ebea3c03d36f 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -53,6 +53,7 @@ note: ...does not necessarily outlive the lifetime `'c` as defined here | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index e2b177b951cc9..0e2c6c60b6e3a 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -2,14 +2,17 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/builtin-superkinds-self-type.rs:10:16 | LL | impl Foo for T { } - | ^^^ ...so that the type `T` will meet its required lifetime bounds... + | ^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/builtin-superkinds-self-type.rs:6:24 | LL | trait Foo : Sized+Sync+'static { | ^^^^^^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl Foo for T { } | +++++++++ diff --git a/tests/ui/cast/unsized-struct-cast.rs b/tests/ui/cast/unsized-struct-cast.rs new file mode 100644 index 0000000000000..52bb6cedcd6d7 --- /dev/null +++ b/tests/ui/cast/unsized-struct-cast.rs @@ -0,0 +1,6 @@ +pub struct Data([u8]); + +fn main(){ + const _: *const Data = &[] as *const Data; + //~^ ERROR: casting `&[_; 0]` as `*const Data` is invalid +} diff --git a/tests/ui/cast/unsized-struct-cast.stderr b/tests/ui/cast/unsized-struct-cast.stderr new file mode 100644 index 0000000000000..79b3d973c32fd --- /dev/null +++ b/tests/ui/cast/unsized-struct-cast.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `&[_; 0]` as `*const Data` is invalid + --> $DIR/unsized-struct-cast.rs:4:28 + | +LL | const _: *const Data = &[] as *const Data; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr index 9ce4710d69bc0..75df314e0baa7 100644 --- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr +++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr @@ -25,6 +25,7 @@ LL | #![cfg_attr(foo, crate_type="bin")] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #91632 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `crate_name` within an `#![cfg_attr] attribute is deprecated` --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 @@ -34,6 +35,7 @@ LL | #![cfg_attr(foo, crate_name="bar")] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #91632 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr index e773d5d83ccfa..c705152d9fc66 100644 --- a/tests/ui/check-cfg/values-target-json.stderr +++ b/tests/ui/check-cfg/values-target-json.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 1f7758146563f..b381f5a4a0a15 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr index e468f6be791fe..eeb4094524243 100644 --- a/tests/ui/closure_context/issue-26046-fn-mut.stderr +++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr @@ -9,7 +9,7 @@ LL | num += 1; LL | Box::new(closure) | ----------------- the requirement to implement `Fn` derives from here | - = note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]>` to `Box<(dyn Fn() + 'static)>` + = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}>` to `Box<(dyn Fn() + 'static)>` error: aborting due to previous error diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr index 41f60327ce061..24773a1d7e351 100644 --- a/tests/ui/closure_context/issue-26046-fn-once.stderr +++ b/tests/ui/closure_context/issue-26046-fn-once.stderr @@ -9,7 +9,7 @@ LL | vec LL | Box::new(closure) | ----------------- the requirement to implement `Fn` derives from here | - = note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]>` to `Box<(dyn Fn() -> Vec + 'static)>` + = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}>` to `Box<(dyn Fn() -> Vec + 'static)>` error: aborting due to previous error diff --git a/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2018.stderr b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2018.stderr new file mode 100644 index 0000000000000..394629c000136 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2018.stderr @@ -0,0 +1,33 @@ +error[E0505]: cannot move out of `value` because it is borrowed + --> $DIR/if-let-guards-errors.rs:16:13 + | +LL | let f = |x: &E| { + | ------- borrow of `value` occurs here +LL | match &x { +LL | E::Number(_) if let E::Number(ref mut n) = *value => { } + | ------ borrow occurs due to use in closure +... +LL | let x = value; + | ^^^^^ move out of `value` occurs here +LL | +LL | drop(f); + | - borrow later used here + +error[E0382]: use of moved value: `value` + --> $DIR/if-let-guards-errors.rs:28:13 + | +LL | fn if_let_move(value: Box) { + | ----- move occurs because `value` has type `Box`, which does not implement the `Copy` trait +LL | let f = |x: &E| { + | ------- value moved into closure here +LL | match &x { +LL | E::Number(_) if let E::String(s) = *value => { } + | ------ variable moved due to use in closure +... +LL | let x = value; + | ^^^^^ value used here after move + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2021.stderr b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2021.stderr new file mode 100644 index 0000000000000..5672845019b8f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.e2021.stderr @@ -0,0 +1,33 @@ +error[E0505]: cannot move out of `value` because it is borrowed + --> $DIR/if-let-guards-errors.rs:16:13 + | +LL | let f = |x: &E| { + | ------- borrow of `*value` occurs here +LL | match &x { +LL | E::Number(_) if let E::Number(ref mut n) = *value => { } + | ------ borrow occurs due to use in closure +... +LL | let x = value; + | ^^^^^ move out of `value` occurs here +LL | +LL | drop(f); + | - borrow later used here + +error[E0382]: use of moved value: `value` + --> $DIR/if-let-guards-errors.rs:28:13 + | +LL | fn if_let_move(value: Box) { + | ----- move occurs because `value` has type `Box`, which does not implement the `Copy` trait +LL | let f = |x: &E| { + | ------- value moved into closure here +LL | match &x { +LL | E::Number(_) if let E::String(s) = *value => { } + | ------ variable moved due to use in closure +... +LL | let x = value; + | ^^^^^ value used here after move + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.rs b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.rs new file mode 100644 index 0000000000000..17e38c033b168 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/if-let-guards-errors.rs @@ -0,0 +1,37 @@ +// Check the if let guards don't force capture by value +// revisions: e2018 e2021 +//[e2018] edition:2018 +//[e2021] edition:2021 + +#![feature(if_let_guard)] +#![allow(irrefutable_let_patterns)] + +fn if_let_ref_mut(mut value: Box) { + let f = |x: &E| { + match &x { + E::Number(_) if let E::Number(ref mut n) = *value => { } + _ => {} + } + }; + let x = value; + //~^ ERROR cannot move out of `value` because it is borrowed + drop(f); +} + +fn if_let_move(value: Box) { + let f = |x: &E| { + match &x { + E::Number(_) if let E::String(s) = *value => { } + _ => {} + } + }; + let x = value; + //~^ ERROR use of moved value: `value` +} + +enum E { + String(String), + Number(i32), +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/if-let-guards.rs b/tests/ui/closures/2229_closure_analysis/match/if-let-guards.rs new file mode 100644 index 0000000000000..fa331707be465 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/if-let-guards.rs @@ -0,0 +1,55 @@ +// Check the if let guards don't force capture by value +// revisions: e2018 e2021 +// check-pass +//[e2018] edition:2018 +//[e2021] edition:2021 + +#![feature(if_let_guard)] +#![allow(irrefutable_let_patterns)] + +fn if_let_underscore(value: Box) { + |x: &E| { + match &x { + E::Number(_) if let _ = *value => { } + _ => {} + } + }; + let x = value; +} + +fn if_let_copy(value: Box) { + |x: &E| { + match &x { + E::Number(_) if let E::Number(n) = *value => { } + _ => {} + } + }; + let x = value; +} + +fn if_let_ref(value: Box) { + |x: &E| { + match &x { + E::Number(_) if let E::Number(ref n) = *value => { } + _ => {} + } + }; + let x = value; +} + +fn if_let_ref_mut(mut value: Box) { + |x: &E| { + match &x { + E::Number(_) if let E::Number(ref mut n) = *value => { } + _ => {} + } + }; + let x = value; +} + +enum E { + String(String), + Number(i32), +} + +fn main() {} diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index ed829fc98f86f..6f9c309edda2e 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/add_semicolon_non_block_closure.rs:8:12 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | foo(|| bar()) | ^^^^^ expected `()`, found `i32` | diff --git a/tests/ui/closures/binder/implicit-return.stderr b/tests/ui/closures/binder/implicit-return.stderr index 5bfb97113344a..35db34ce21d1c 100644 --- a/tests/ui/closures/binder/implicit-return.stderr +++ b/tests/ui/closures/binder/implicit-return.stderr @@ -1,8 +1,8 @@ error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/implicit-return.rs:4:34 + --> $DIR/implicit-return.rs:4:33 | LL | let _f = for<'a> |_: &'a ()| {}; - | ------- ^ + | ------- ^ | | | `for<...>` is here diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index 779a08a44e5a8..cec2a60ba28c8 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -41,10 +41,10 @@ LL | let _ = for<'a> |x: &'a ()| -> &() { x }; | ^ explicit lifetime name needed here error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/implicit-stuff.rs:5:22 + --> $DIR/implicit-stuff.rs:5:21 | LL | let _ = for<> || {}; - | ----- ^ + | ----- ^ | | | `for<...>` is here diff --git a/tests/ui/closures/capture-unsized-by-move.rs b/tests/ui/closures/capture-unsized-by-move.rs new file mode 100644 index 0000000000000..1148e34ac675d --- /dev/null +++ b/tests/ui/closures/capture-unsized-by-move.rs @@ -0,0 +1,10 @@ +// compile-flags: --crate-type=lib + +#![feature(unsized_fn_params)] + +pub fn f(k: dyn std::fmt::Display) { + let k2 = move || { + k.to_string(); + //~^ ERROR the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time + }; +} diff --git a/tests/ui/closures/capture-unsized-by-move.stderr b/tests/ui/closures/capture-unsized-by-move.stderr new file mode 100644 index 0000000000000..d7fafc8cadd7b --- /dev/null +++ b/tests/ui/closures/capture-unsized-by-move.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time + --> $DIR/capture-unsized-by-move.rs:7:9 + | +LL | let k2 = move || { + | -- this closure captures all values by move +LL | k.to_string(); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn std::fmt::Display + 'static)` + = note: all values captured by value by a closure must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/capture-unsized-by-ref.rs b/tests/ui/closures/capture-unsized-by-ref.rs new file mode 100644 index 0000000000000..c9e4a5903d932 --- /dev/null +++ b/tests/ui/closures/capture-unsized-by-ref.rs @@ -0,0 +1,10 @@ +// build-pass +// compile-flags: --crate-type=lib + +#![feature(unsized_fn_params)] + +pub fn f(k: dyn std::fmt::Display) { + let k2 = || { + k.to_string(); + }; +} diff --git a/tests/ui/closures/closure-no-fn-1.stderr b/tests/ui/closures/closure-no-fn-1.stderr index eab7482e6c4a1..87e670bb0b393 100644 --- a/tests/ui/closures/closure-no-fn-1.stderr +++ b/tests/ui/closures/closure-no-fn-1.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:36]` + found closure `{closure@$DIR/closure-no-fn-1.rs:6:29: 6:36}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-1.rs:6:39 | diff --git a/tests/ui/closures/closure-no-fn-2.stderr b/tests/ui/closures/closure-no-fn-2.stderr index e1f0143abfe0a..7c7e9d0ce125b 100644 --- a/tests/ui/closures/closure-no-fn-2.stderr +++ b/tests/ui/closures/closure-no-fn-2.stderr @@ -7,7 +7,7 @@ LL | let bar: fn() -> u8 = || { b }; | expected due to this | = note: expected fn pointer `fn() -> u8` - found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:29]` + found closure `{closure@$DIR/closure-no-fn-2.rs:6:27: 6:29}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-2.rs:6:32 | diff --git a/tests/ui/closures/closure-no-fn-3.stderr b/tests/ui/closures/closure-no-fn-3.stderr index 6009389b1bb2c..276e766e8065b 100644 --- a/tests/ui/closures/closure-no-fn-3.stderr +++ b/tests/ui/closures/closure-no-fn-3.stderr @@ -1,4 +1,4 @@ -error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:28: 6:30]` as `fn() -> u8` +error[E0605]: non-primitive cast: `{closure@$DIR/closure-no-fn-3.rs:6:28: 6:30}` as `fn() -> u8` --> $DIR/closure-no-fn-3.rs:6:27 | LL | let baz: fn() -> u8 = (|| { b }) as fn() -> u8; diff --git a/tests/ui/closures/closure-no-fn-4.stderr b/tests/ui/closures/closure-no-fn-4.stderr index d1b7048841a42..0bec11ab61fc3 100644 --- a/tests/ui/closures/closure-no-fn-4.stderr +++ b/tests/ui/closures/closure-no-fn-4.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____- `match` arms have incompatible types | = note: expected fn pointer `fn(usize) -> usize` - found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:21]` + found closure `{closure@$DIR/closure-no-fn-4.rs:5:18: 5:21}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-4.rs:5:26 | diff --git a/tests/ui/closures/closure-no-fn-5.stderr b/tests/ui/closures/closure-no-fn-5.stderr index a33b847ea92d9..13d19495d23d9 100644 --- a/tests/ui/closures/closure-no-fn-5.stderr +++ b/tests/ui/closures/closure-no-fn-5.stderr @@ -7,7 +7,7 @@ LL | let bar: fn() -> u8 = || { a; b; c; d; e }; | expected due to this | = note: expected fn pointer `fn() -> u8` - found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:29]` + found closure `{closure@$DIR/closure-no-fn-5.rs:10:27: 10:29}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-5.rs:10:32 | diff --git a/tests/ui/closures/closure-reform-bad.stderr b/tests/ui/closures/closure-reform-bad.stderr index 4c40f70b9d0a8..6bb59813157b2 100644 --- a/tests/ui/closures/closure-reform-bad.stderr +++ b/tests/ui/closures/closure-reform-bad.stderr @@ -9,7 +9,7 @@ LL | call_bare(f) | arguments to this function are incorrect | = note: expected fn pointer `for<'a> fn(&'a str)` - found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:22]` + found closure `{closure@$DIR/closure-reform-bad.rs:10:13: 10:22}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-reform-bad.rs:10:43 | diff --git a/tests/ui/closures/closure_cap_coerce_many_fail.stderr b/tests/ui/closures/closure_cap_coerce_many_fail.stderr index ca8a43328a9e4..958439e7dd061 100644 --- a/tests/ui/closures/closure_cap_coerce_many_fail.stderr +++ b/tests/ui/closures/closure_cap_coerce_many_fail.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____- `match` arms have incompatible types | = note: expected fn item `fn(i32, i32) -> i32 {add}` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:22]` + found closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:22}` error[E0308]: `match` arms have incompatible types --> $DIR/closure_cap_coerce_many_fail.rs:18:16 @@ -23,15 +23,15 @@ LL | | "+" => |a, b| (a + b) as i32, | | --------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` + | | this is found to be of type `{closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22}` LL | | "-" => |a, b| (a - b + cap) as i32, | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:22]` + = note: expected closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22}` + found closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:22}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object @@ -44,15 +44,15 @@ LL | | "+" => |a, b| (a + b + cap) as i32, | | --------------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` + | | this is found to be of type `{closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22}` LL | | "-" => |a, b| (a - b) as i32, | | ^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:22]` + = note: expected closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22}` + found closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:22}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object @@ -65,15 +65,15 @@ LL | | "+" => |a, b| (a + b + cap) as i32, | | --------------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` + | | this is found to be of type `{closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22}` LL | | "-" => |a, b| (a - b + cap) as i32, | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:22]` + = note: expected closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22}` + found closure `{closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:22}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object diff --git a/tests/ui/closures/issue-112547.rs b/tests/ui/closures/issue-112547.rs new file mode 100644 index 0000000000000..8ecb2abccd4f9 --- /dev/null +++ b/tests/ui/closures/issue-112547.rs @@ -0,0 +1,15 @@ +#![feature(non_lifetime_binders)] + //~^ WARNING the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + +pub fn bar() +where + for V: IntoIterator +//~^ ERROR cannot find type `V` in this scope [E0412] +{ +} + +fn main() { + bar(); +} diff --git a/tests/ui/closures/issue-112547.stderr b/tests/ui/closures/issue-112547.stderr new file mode 100644 index 0000000000000..d86b05dc6a7bf --- /dev/null +++ b/tests/ui/closures/issue-112547.stderr @@ -0,0 +1,23 @@ +error[E0412]: cannot find type `V` in this scope + --> $DIR/issue-112547.rs:8:4 + | +LL | }> V: IntoIterator + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | pub fn bar() + | +++ + +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-112547.rs:1:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/closures/issue-90871.stderr b/tests/ui/closures/issue-90871.stderr index 4a578b4d7f536..ef1cb213f73be 100644 --- a/tests/ui/closures/issue-90871.stderr +++ b/tests/ui/closures/issue-90871.stderr @@ -14,7 +14,7 @@ LL | type_ascribe!(2, n([u8; || 1])) | ^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/issue-90871.rs:4:29: 4:31]` + found closure `{closure@$DIR/issue-90871.rs:4:29: 4:31}` help: use parentheses to call this closure | LL | type_ascribe!(2, n([u8; (|| 1)()])) diff --git a/tests/ui/closures/print/closure-print-generic-1.stderr b/tests/ui/closures/print/closure-print-generic-1.stderr index b21734f025767..2697f93b14c2b 100644 --- a/tests/ui/closures/print/closure-print-generic-1.stderr +++ b/tests/ui/closures/print/closure-print-generic-1.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c` --> $DIR/closure-print-generic-1.rs:17:5 | LL | let c = to_fn_once(move || { - | - move occurs because `c` has type `[closure@$DIR/closure-print-generic-1.rs:12:24: 12:31]`, which does not implement the `Copy` trait + | - move occurs because `c` has type `{closure@$DIR/closure-print-generic-1.rs:12:24: 12:31}`, which does not implement the `Copy` trait ... LL | c(); | --- `c` moved due to this call diff --git a/tests/ui/closures/print/closure-print-generic-2.stderr b/tests/ui/closures/print/closure-print-generic-2.stderr index e53277a9396f3..ced0be9458b8e 100644 --- a/tests/ui/closures/print/closure-print-generic-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-2.stderr @@ -9,7 +9,7 @@ LL | let c1: () = c; | expected due to this | = note: expected unit type `()` - found closure `[closure@$DIR/closure-print-generic-2.rs:5:17: 5:19]` + found closure `{closure@$DIR/closure-print-generic-2.rs:5:17: 5:19}` help: use parentheses to call this closure | LL | let c1: () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index 49453b0538b3d..6e3659b95ea8d 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]]` + found closure `{mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr index 9a1f18fa8550d..5e8a6b1a73aa7 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c` --> $DIR/closure-print-generic-verbose-1.rs:17:5 | LL | let c = to_fn_once(move|| { - | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'?9 str>, T)]`, which does not implement the `Copy` trait + | - move occurs because `c` has type `{f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'?9 str>, T)}`, which does not implement the `Copy` trait ... LL | c(); | --- `c` moved due to this call diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index d2deba3dd84fb..f1fc35e755cca 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]]` + found closure `{f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr index acc81f5e466f1..3f9160fe5fa97 100644 --- a/tests/ui/closures/print/closure-print-verbose.stderr +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]]` + found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | diff --git a/tests/ui/codegen/issue-79865-llvm-miscompile.rs b/tests/ui/codegen/issue-79865-llvm-miscompile.rs new file mode 100644 index 0000000000000..6f994a5cb741b --- /dev/null +++ b/tests/ui/codegen/issue-79865-llvm-miscompile.rs @@ -0,0 +1,38 @@ +// run-pass +// only-x86_64 +// compile-flags: -C opt-level=3 + +// Regression test for issue #79865. +// The assertion will fail when compiled with Rust 1.56..=1.59 +// due to an LLVM miscompilation. + +use std::arch::x86_64::*; + +fn main() { + if is_x86_feature_detected!("avx") { + let res: [f64; 4] = unsafe { std::mem::transmute::<_, _>(first()) }; + assert_eq!(res, [22.0, 44.0, 66.0, 88.0]); + } +} + +#[target_feature(enable = "avx")] +unsafe fn first() -> __m256d { + second() +} + +unsafe fn second() -> __m256d { + let v0 = _mm256_setr_pd(1.0, 2.0, 3.0, 4.0); + let v1 = _mm256_setr_pd(10.0, 20.0, 30.0, 40.0); + + // needs to be called twice to hit the miscompilation + let (add, _) = add_sub(v0, v1); + let (add, _) = add_sub(add, add); + add +} + +#[inline(never)] // needed to hit the miscompilation +unsafe fn add_sub(v1: __m256d, v0: __m256d) -> (__m256d, __m256d) { + let add = _mm256_add_pd(v0, v1); + let sub = _mm256_sub_pd(v0, v1); + (add, sub) +} diff --git a/tests/ui/codegen/subtyping-enforces-type-equality.stderr b/tests/ui/codegen/subtyping-enforces-type-equality.stderr deleted file mode 100644 index 870ca0f839fee..0000000000000 --- a/tests/ui/codegen/subtyping-enforces-type-equality.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type. See the issues/114858 diff --git a/tests/ui/codemap_tests/tab.stderr b/tests/ui/codemap_tests/tab.stderr index c3f19d20d3952..d2de7486557f7 100644 --- a/tests/ui/codemap_tests/tab.stderr +++ b/tests/ui/codemap_tests/tab.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/tab.rs:8:2 | LL | fn foo() { - | - help: try adding a return type: `-> &'static str` + | - help: try adding a return type: `-> &'static str` LL | "bar boo" | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&str` diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr index aa5ec6b5ae1fd..646044ae41abc 100644 --- a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr +++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -29,10 +29,10 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:14:27 | LL | let _ = type_ascribe!(Box::new( { |x| (x as u8) }), Box _>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:14:39]>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:14:39}>` | = note: expected struct `Box u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42]>` + found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42}>` error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:15:27 @@ -83,10 +83,10 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:22:27 | LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _); - | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&[closure@coerce-expect-unsized-ascribed.rs:22:30]` + | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@coerce-expect-unsized-ascribed.rs:22:30}` | = note: expected reference `&dyn Fn(i32) -> u8` - found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33]` + found reference `&{closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33}` error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:23:27 @@ -119,10 +119,10 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:27:27 | LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box _>); - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:27:36]>` + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:27:36}>` | = note: expected struct `Box u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39]>` + found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39}>` error: aborting due to 14 previous errors diff --git a/tests/ui/coercion/issue-53475.stderr b/tests/ui/coercion/issue-53475.stderr index 522c50dca9508..4778611bf1b53 100644 --- a/tests/ui/coercion/issue-53475.stderr +++ b/tests/ui/coercion/issue-53475.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-53475.rs:10:1 | LL | impl CoerceUnsized> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl CoerceUnsized> for Foo {} | +++++++++ diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr similarity index 87% rename from tests/ui/coherence/coherence-overlap-downstream-inherent.stderr rename to tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr index bbce4b530b4d6..2938bc629b2cc 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:7:26 + --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 | LL | impl Sweet { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` @@ -8,7 +8,7 @@ LL | impl Sweet { fn dummy(&self) { } } | --------------- other definition for `dummy` error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:13:38 + --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 | LL | impl A where T: Bar { fn f(&self) {} } | ^^^^^^^^^^^ duplicate definitions for `f` diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr new file mode 100644 index 0000000000000..2938bc629b2cc --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr @@ -0,0 +1,23 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 + | +LL | impl Sweet { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Sweet { fn dummy(&self) { } } + | --------------- other definition for `dummy` + +error[E0592]: duplicate definitions with name `f` + --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 + | +LL | impl A where T: Bar { fn f(&self) {} } + | ^^^^^^^^^^^ duplicate definitions for `f` +LL | +LL | impl A { fn f(&self) {} } + | ----------- other definition for `f` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs index 5dea33e330b62..2c3ef4fd3f718 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream.stderr b/tests/ui/coherence/coherence-overlap-downstream.next.stderr similarity index 79% rename from tests/ui/coherence/coherence-overlap-downstream.stderr rename to tests/ui/coherence/coherence-overlap-downstream.next.stderr index 7f373e595a35f..6c2e9466b4bde 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:8:1 + --> $DIR/coherence-overlap-downstream.rs:11:1 | LL | impl Sweet for T { } | ------------------------- first implementation here @@ -7,10 +7,10 @@ LL | impl Sweet for T { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:14:1 + --> $DIR/coherence-overlap-downstream.rs:17:1 | LL | impl Foo for T where T: Bar {} - | ----------------------- first implementation here + | --------------------------------------- first implementation here LL | impl Foo for i32 {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr new file mode 100644 index 0000000000000..6c2e9466b4bde --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream.old.stderr @@ -0,0 +1,21 @@ +error[E0119]: conflicting implementations of trait `Sweet` + --> $DIR/coherence-overlap-downstream.rs:11:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for T { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` + --> $DIR/coherence-overlap-downstream.rs:17:1 + | +LL | impl Foo for T where T: Bar {} + | --------------------------------------- first implementation here +LL | impl Foo for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs index 738ec0e3d4550..a4e559604a001 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.rs +++ b/tests/ui/coherence/coherence-overlap-downstream.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr similarity index 89% rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr index 3ad818cbc36dd..c02a679c149cf 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25 + --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 | LL | impl Cake { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr new file mode 100644 index 0000000000000..c02a679c149cf --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 + | +LL | impl Cake { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Cake> { fn dummy(&self) { } } + | --------------- other definition for `dummy` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs index a272e620fcab3..a7c90a6b8c8d0 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516.next.stderr index cd398426704cb..a4e87af8ac40e 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:8:1 + --> $DIR/coherence-overlap-issue-23516.rs:11:1 | LL | impl Sweet for T { } | ------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr new file mode 100644 index 0000000000000..a4e87af8ac40e --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` + --> $DIR/coherence-overlap-issue-23516.rs:11:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs index 63e42e8f412dd..c846d39716bbd 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-upstream.stderr b/tests/ui/coherence/coherence-overlap-upstream.stderr index f6145c1883a09..8272c88758607 100644 --- a/tests/ui/coherence/coherence-overlap-upstream.stderr +++ b/tests/ui/coherence/coherence-overlap-upstream.stderr @@ -2,7 +2,7 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i16` --> $DIR/coherence-overlap-upstream.rs:13:1 | LL | impl Foo for T where T: Remote {} - | ----------------- first implementation here + | --------------------------------- first implementation here LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` | diff --git a/tests/ui/coherence/coherence-wasm-bindgen.stderr b/tests/ui/coherence/coherence-wasm-bindgen.stderr index 89615f0fbc63b..600cd42d8c69d 100644 --- a/tests/ui/coherence/coherence-wasm-bindgen.stderr +++ b/tests/ui/coherence/coherence-wasm-bindgen.stderr @@ -1,11 +1,17 @@ error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn Fn(&_) -> _` --> $DIR/coherence-wasm-bindgen.rs:28:1 | -LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) - | ------------------------------------------------------------ first implementation here +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +LL | | where +LL | | A: FromWasmAbi, +LL | | R: ReturnWasmAbi, + | |_____________________- first implementation here ... -LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&dyn Fn(&_) -> _` +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +LL | | where +LL | | A: RefFromWasmAbi, +LL | | R: ReturnWasmAbi, + | |_____________________^ conflicting implementation for `&dyn Fn(&_) -> _` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #56105 diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr similarity index 51% rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr index 4ddd712b27c88..9b2dbc66ca7fd 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr @@ -1,11 +1,14 @@ error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 + --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 | -LL | impl From<()> for S { - | ------------------- first implementation here +LL | impl From<()> for S { + | ------------------- first implementation here ... -LL | impl From for S - | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` +LL | / impl From for S +LL | | +LL | | where +LL | | I: Iterator, + | |___________________________^ conflicting implementation for `S` | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr new file mode 100644 index 0000000000000..9b2dbc66ca7fd --- /dev/null +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr @@ -0,0 +1,17 @@ +error[E0119]: conflicting implementations of trait `From<()>` for type `S` + --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 + | +LL | impl From<()> for S { + | ------------------- first implementation here +... +LL | / impl From for S +LL | | +LL | | where +LL | | I: Iterator, + | |___________________________^ conflicting implementation for `S` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs index 5b11c78ab2605..743e80d3f1818 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -1,3 +1,6 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + struct S; impl From<()> for S { diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index 89289767b838b..ecc73d994f9ac 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -1,11 +1,16 @@ error: implementations of `PartialEq>` for `Interval<_>` will conflict in the future --> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1 | -LL | #[derive(PartialEq, Default)] - | --------- the second impl is here +LL | #[derive(PartialEq, Default)] + | --------- the second impl is here ... -LL | impl PartialEq for Interval - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the first impl is here +LL | / impl PartialEq for Interval +LL | | +LL | | +LL | | where +LL | | T: Borrow, +LL | | Q: ?Sized + PartialOrd, + | |___________________________^ the first impl is here | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #114040 diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr index f632a53f264e0..a87b713c2b4bd 100644 --- a/tests/ui/compare-method/bad-self-type.stderr +++ b/tests/ui/compare-method/bad-self-type.stderr @@ -28,10 +28,10 @@ LL | fn foo(self); found signature `fn(Box)` error[E0053]: method `bar` has an incompatible type for trait - --> $DIR/bad-self-type.rs:24:18 + --> $DIR/bad-self-type.rs:24:17 | LL | fn bar(self) {} - | ^ expected `Option<()>`, found `()` + | ^ expected `Option<()>`, found `()` | note: type in trait --> $DIR/bad-self-type.rs:18:21 diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index d5b4349c00f6f..12557ff636041 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -74,6 +74,7 @@ LL | #[cfg(feature = $expr)] LL | generate_s10!(concat!("nonexistent")); | ------------------------------------- in this macro invocation | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 11 previous errors diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr index 34debb6831734..aaf953a66d528 100644 --- a/tests/ui/confuse-field-and-method/issue-33784.stderr +++ b/tests/ui/confuse-field-and-method/issue-33784.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope +error[E0599]: no method named `closure` found for reference `&Obj<{closure@$DIR/issue-33784.rs:25:43: 25:45}>` in the current scope --> $DIR/issue-33784.rs:27:7 | LL | p.closure(); @@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p LL | (p.closure)(); | + + -error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope +error[E0599]: no method named `fn_ptr` found for reference `&&Obj<{closure@$DIR/issue-33784.rs:25:43: 25:45}>` in the current scope --> $DIR/issue-33784.rs:29:7 | LL | q.fn_ptr(); diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs index 0da68ae757351..c4d2d02ba7034 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs @@ -5,7 +5,7 @@ fn check(_: impl std::marker::ConstParamTy) {} fn main() { check(main); //~ error: `fn() {main}` can't be used as a const parameter type - check(|| {}); //~ error: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type + check(|| {}); //~ error: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as a const parameter type check(main as fn()); //~ error: `fn()` can't be used as a const parameter type check(&mut ()); //~ error: `&mut ()` can't be used as a const parameter type check(&mut () as *mut ()); //~ error: `*mut ()` can't be used as a const parameter type diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr index 48910b82a1032..d96491f4f20ea 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr @@ -16,11 +16,11 @@ help: use parentheses to call this function LL | check(main()); | ++ -error[E0277]: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type +error[E0277]: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:8:11 | LL | check(|| {}); - | ----- ^^^^^ the trait `ConstParamTy` is not implemented for closure `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` + | ----- ^^^^^ the trait `ConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` | | | required by a bound introduced by this call | diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs index 08f7c5cb5423e..7174d1ec4f206 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -10,10 +10,12 @@ struct CantParam(ImplementsConstParamTy); impl std::marker::ConstParamTy for CantParam {} //~^ error: the type `CantParam` does not `#[derive(Eq)]` //~| error: the type `CantParam` does not `#[derive(PartialEq)]` +//~| the trait bound `CantParam: Eq` is not satisfied #[derive(std::marker::ConstParamTy)] //~^ error: the type `CantParamDerive` does not `#[derive(Eq)]` //~| error: the type `CantParamDerive` does not `#[derive(PartialEq)]` +//~| the trait bound `CantParamDerive: Eq` is not satisfied struct CantParamDerive(ImplementsConstParamTy); fn check() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index 43c5b96dc7cb8..2cf7cc07dbe5e 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -1,3 +1,17 @@ +error[E0277]: the trait bound `CantParam: Eq` is not satisfied + --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36 + | +LL | impl std::marker::ConstParamTy for CantParam {} + | ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam` + | +note: required by a bound in `ConstParamTy` + --> $SRC_DIR/core/src/marker.rs:LL:COL +help: consider annotating `CantParam` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct CantParam(ImplementsConstParamTy); + | + error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]` --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36 | @@ -16,8 +30,23 @@ LL | impl std::marker::ConstParamTy for CantParam {} note: required by a bound in `ConstParamTy` --> $SRC_DIR/core/src/marker.rs:LL:COL +error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10 + | +LL | #[derive(std::marker::ConstParamTy)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` + | +note: required by a bound in `ConstParamTy` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `CantParamDerive` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct CantParamDerive(ImplementsConstParamTy); + | + error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10 | LL | #[derive(std::marker::ConstParamTy)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive` @@ -27,7 +56,7 @@ note: required by a bound in `ConstParamTy` = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:10 | LL | #[derive(std::marker::ConstParamTy)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive` @@ -36,6 +65,6 @@ note: required by a bound in `ConstParamTy` --> $SRC_DIR/core/src/marker.rs:LL:COL = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs new file mode 100644 index 0000000000000..a83830178d40e --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs @@ -0,0 +1,44 @@ +// Test that when adt_const_params is not enabled, we suggest adding the feature only when +// it would be possible for the type to be used as a const generic or when it's likely +// possible for the user to fix their type to be used. + +// Can never be used as const generics. +fn uwu_0() {} +//~^ ERROR: forbidden as the type of a const generic + +// Needs the feature but can be used, so suggest adding the feature. +fn owo_0() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// Can only be used in const generics with changes. +struct Meow { + meow: u8, +} + +fn meow_0() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_1() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_2() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_3() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// This is suboptimal that it thinks it can be used +// but better to suggest the feature to the user. +fn meow_4() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// Non-local ADT that does not impl `ConstParamTy` +fn nya_0() {} +//~^ ERROR: forbidden as the type of a const generic +fn nya_1>() {} +//~^ ERROR: forbidden as the type of a const generic + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr new file mode 100644 index 0000000000000..04527e3158ed1 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr @@ -0,0 +1,80 @@ +error: `&'static mut ()` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:6:19 + | +LL | fn uwu_0() {} + | ^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: `&'static u32` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:10:19 + | +LL | fn owo_0() {} + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `Meow` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:19:20 + | +LL | fn meow_0() {} + | ^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `&'static Meow` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:22:20 + | +LL | fn meow_1() {} + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `[Meow; 100]` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:25:20 + | +LL | fn meow_2() {} + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `(Meow, u8)` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:28:20 + | +LL | fn meow_3() {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `(Meow, String)` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:34:20 + | +LL | fn meow_4() {} + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `String` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:39:19 + | +LL | fn nya_0() {} + | ^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: `Vec` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:41:19 + | +LL | fn nya_1>() {} + | ^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr index d7e5e50cba82d..6d5cd45479ec7 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -39,6 +39,7 @@ note: associated constant defined here | LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/const-argument-if-length.full.stderr b/tests/ui/const-generics/const-argument-if-length.full.stderr index 7997026dfe498..315b0f0a06485 100644 --- a/tests/ui/const-generics/const-argument-if-length.full.stderr +++ b/tests/ui/const-generics/const-argument-if-length.full.stderr @@ -1,3 +1,11 @@ +error: unconstrained generic constant + --> $DIR/const-argument-if-length.rs:17:10 + | +LL | pad: [u8; is_zst::()], + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); is_zst::()]:` + error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/const-argument-if-length.rs:15:12 | @@ -22,14 +30,6 @@ help: the `Box` type always has a statically known size and allocates its conten LL | value: Box, | ++++ + -error: unconstrained generic constant - --> $DIR/const-argument-if-length.rs:17:10 - | -LL | pad: [u8; is_zst::()], - | ^^^^^^^^^^^^^^^^^^^ - | - = help: try adding a `where` bound using this expression: `where [(); is_zst::()]:` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr index 656bc29466f23..ffe4528598850 100644 --- a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -35,7 +35,7 @@ LL | struct A; | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:14:15 @@ -44,7 +44,7 @@ LL | impl A { | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:22:15 @@ -53,7 +53,7 @@ LL | impl B for A {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:26:17 @@ -62,7 +62,7 @@ LL | fn bar() {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:17:21 @@ -71,7 +71,7 @@ LL | fn foo(&self) {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 10 previous errors diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr index f829526ca1dc8..daeeadeed7cfd 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -21,7 +21,7 @@ LL | pub struct Dependent([(); N]); | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `[u8; N]` is forbidden as the type of a const generic parameter --> $DIR/const-param-type-depends-on-const-param.rs:15:35 @@ -30,7 +30,7 @@ LL | pub struct SelfDependent; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr index 89ca36b0f6314..aeb19dc75322d 100644 --- a/tests/ui/const-generics/float-generic.simple.stderr +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -5,7 +5,6 @@ LL | fn foo() {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: aborting due to previous error diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr index d984449e6ca6e..2d316fba1e90a 100644 --- a/tests/ui/const-generics/fn-const-param-call.min.stderr +++ b/tests/ui/const-generics/fn-const-param-call.min.stderr @@ -3,12 +3,16 @@ error: using function pointers as const generic parameters is forbidden | LL | struct Wrapper u32>; | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/fn-const-param-call.rs:13:15 | LL | impl u32> Wrapper { | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr index f0767a10994a5..a7afa48427594 100644 --- a/tests/ui/const-generics/fn-const-param-infer.min.stderr +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr index 956e9c9c988a4..64d1e0bcff4e0 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -23,7 +23,7 @@ LL | struct B { | ^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index 79ed82e02e0d6..25a455d3308a2 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -3,7 +3,7 @@ error: internal compiler error: compiler/rustc_const_eval/src/interpret/step.rs: Box query stack during panic: -#0 [eval_to_allocation_raw] const-evaluating + checking `::{constant#0}` +#0 [eval_to_allocation_raw] const-evaluating + checking `::{constant#0}` #1 [eval_to_valtree] evaluating type-level constant end of query stack error: aborting due to previous error diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index b8a1027c9ebdb..4c45339b93b37 100644 --- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -14,7 +14,7 @@ LL | trait Trait {} | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr index 71a7051f25bfa..fc10aba0fecd0 100644 --- a/tests/ui/const-generics/issues/issue-56445-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr @@ -13,7 +13,7 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index 9c0e5179cc4c2..eb8b9732f58c8 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -13,7 +13,7 @@ LL | fn foo() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index 9f6c7ccf3fe74..9d80f1cd01bc6 100644 --- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -5,7 +5,7 @@ LL | fn test() { | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr index df04c4896b45a..c8b9f17196aca 100644 --- a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -5,7 +5,7 @@ LL | struct Const {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr index 1b4517087e223..fc6cef9d44e55 100644 --- a/tests/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-71169.min.stderr b/tests/ui/const-generics/issues/issue-71169.min.stderr index ebfb24bec28df..bba92f32a7842 100644 --- a/tests/ui/const-generics/issues/issue-71169.min.stderr +++ b/tests/ui/const-generics/issues/issue-71169.min.stderr @@ -13,7 +13,7 @@ LL | fn foo() {} | ^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index e1e140071fc13..e16d3b7a8a469 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -19,12 +19,16 @@ error: using function pointers as const generic parameters is forbidden | LL | pub fn call_me(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/issue-71381.rs:23:19 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr index 715037bd5f1e8..217166d847937 100644 --- a/tests/ui/const-generics/issues/issue-71382.min.stderr +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn test(&self) { | ^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr index b33d7cf9850fa..b01936f4d2513 100644 --- a/tests/ui/const-generics/issues/issue-71611.min.stderr +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -11,6 +11,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn func(outer: A) { | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr index eedd73c4dcc0a..b010996b89692 100644 --- a/tests/ui/const-generics/issues/issue-72352.min.stderr +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { | ^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr index f03354fc472c0..fdf057bdbe47d 100644 --- a/tests/ui/const-generics/issues/issue-73491.min.stderr +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -5,7 +5,7 @@ LL | fn hoge() {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr index 0a7db62472a9f..bed0a02a72673 100644 --- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -5,7 +5,7 @@ LL | fn a() {} | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-74101.min.stderr b/tests/ui/const-generics/issues/issue-74101.min.stderr index 134c248347d3c..7852ce5bcfcea 100644 --- a/tests/ui/const-generics/issues/issue-74101.min.stderr +++ b/tests/ui/const-generics/issues/issue-74101.min.stderr @@ -5,7 +5,7 @@ LL | fn test() {} | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter --> $DIR/issue-74101.rs:9:21 @@ -14,7 +14,7 @@ LL | struct Foo; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr index bbcf8682b7119..affeca167e970 100644 --- a/tests/ui/const-generics/issues/issue-74255.min.stderr +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -5,7 +5,7 @@ LL | fn ice_struct_fn() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr index c37ee93d420fd..54ef1ea1e94c0 100644 --- a/tests/ui/const-generics/issues/issue-74950.min.stderr +++ b/tests/ui/const-generics/issues/issue-74950.min.stderr @@ -5,7 +5,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -14,7 +14,8 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -23,7 +24,8 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -32,7 +34,8 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -41,7 +44,8 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 previous errors diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr index 46af19ef39540..e316b4624a007 100644 --- a/tests/ui/const-generics/issues/issue-75047.min.stderr +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo::value()]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-83249.stderr b/tests/ui/const-generics/issues/issue-83249.stderr index 7491fdc8a693e..5187434ff40e0 100644 --- a/tests/ui/const-generics/issues/issue-83249.stderr +++ b/tests/ui/const-generics/issues/issue-83249.stderr @@ -1,9 +1,18 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/issue-83249.rs:19:9 | LL | let _ = foo([0; 1]); - | ^ + | ^ --- ------ type must be known at this point + | | + | required by a bound introduced by this call | + = note: cannot satisfy `_: Foo` + = help: the trait `Foo` is implemented for `u8` +note: required by a bound in `foo` + --> $DIR/issue-83249.rs:12:11 + | +LL | fn foo(_: [u8; T::N]) -> T { + | ^^^ required by this bound in `foo` help: consider giving this pattern a type | LL | let _: /* Type */ = foo([0; 1]); @@ -11,4 +20,4 @@ LL | let _: /* Type */ = foo([0; 1]); error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/const-generics/lifetime-in-const-param.stderr b/tests/ui/const-generics/lifetime-in-const-param.stderr index 8fd9068e8efd2..c2fcdcf1a7128 100644 --- a/tests/ui/const-generics/lifetime-in-const-param.stderr +++ b/tests/ui/const-generics/lifetime-in-const-param.stderr @@ -11,7 +11,7 @@ LL | struct S<'a, const N: S2>(&'a ()); | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr index 4ddbadb54661b..8cc75dbaff9c3 100644 --- a/tests/ui/const-generics/min_const_generics/complex-types.stderr +++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:6:21 @@ -14,7 +14,7 @@ LL | struct Bar; | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `No` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:11:21 @@ -23,7 +23,7 @@ LL | struct Fez; | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:14:21 @@ -32,7 +32,7 @@ LL | struct Faz; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `!` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:17:21 @@ -41,7 +41,6 @@ LL | struct Fiz; | ^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:20:19 @@ -50,7 +49,7 @@ LL | enum Goo { A, B } | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:23:20 @@ -59,7 +58,7 @@ LL | union Boo { a: () } | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 7 previous errors diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr index 257a9e31e14b2..ca5af5f969f58 100644 --- a/tests/ui/const-generics/nested-type.min.stderr +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -30,7 +30,7 @@ LL | | }]>; | |__^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr index 51ef354e3ed4a..61d055e808473 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied LL | let _ = A; | ^ the trait `Bar<_>` is not implemented for `A<_>` | - = help: the trait `Bar` is implemented for `A<7>` + = help: the trait `Bar<_>` is implemented for `A<7>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 | diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr index 803ed9c959752..9f727231edfbe 100644 --- a/tests/ui/const-generics/projection-as-arg-const.stderr +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -5,7 +5,6 @@ LL | pub fn foo::Identity>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: aborting due to previous error diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr index 04bc46cb4ab12..1eb238255abc2 100644 --- a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -3,12 +3,16 @@ error: using raw pointers as const generic parameters is forbidden | LL | struct Const; | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using raw pointers as const generic parameters is forbidden --> $DIR/raw-ptr-const-param-deref.rs:11:15 | LL | impl Const

{ | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr index 310422aafcd35..13fbc34e51a0d 100644 --- a/tests/ui/const-generics/raw-ptr-const-param.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -3,6 +3,8 @@ error: using raw pointers as const generic parameters is forbidden | LL | struct Const; | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr index fed802f6adc6b..3c086f59b2788 100644 --- a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr +++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -5,7 +5,7 @@ LL | struct ConstString; | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static [u8]` is forbidden as the type of a const generic parameter --> $DIR/slice-const-param-mismatch.rs:9:28 @@ -14,7 +14,7 @@ LL | struct ConstBytes; | ^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr index 53fca6e884a9a..d45f749246c8e 100644 --- a/tests/ui/const-generics/std/const-generics-range.min.stderr +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -5,7 +5,7 @@ LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeFrom` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:13:28 @@ -14,7 +14,7 @@ LL | struct _RangeFrom>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeFull` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:18:28 @@ -23,7 +23,7 @@ LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:24:33 @@ -32,7 +32,7 @@ LL | struct _RangeInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeTo` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:29:26 @@ -41,7 +41,7 @@ LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeToInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:34:35 @@ -50,7 +50,7 @@ LL | struct _RangeToInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr index 039c4276c8b77..f18e149464d3d 100644 --- a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -5,7 +5,7 @@ LL | struct Const; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index b8fbb3979799d..6490592c1e1e6 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> { | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:18:25 @@ -14,7 +14,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr index ad522aead9050..3f42feea562ab 100644 --- a/tests/ui/const-generics/type-dependent/issue-71382.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn test u8>(&self) -> u8 { | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/consts/const-adt-align-mismatch.rs b/tests/ui/consts/const-adt-align-mismatch.rs index bd51bc9f215b4..89b3a9b744bc0 100644 --- a/tests/ui/consts/const-adt-align-mismatch.rs +++ b/tests/ui/consts/const-adt-align-mismatch.rs @@ -12,7 +12,7 @@ enum Foo { } // NOTE(eddyb) Don't make this a const, needs to be a static -// so it is always instantiated as a LLVM constant value. +// so it is always instantiated as an LLVM constant value. static FOO: Foo = Foo::C; fn main() { diff --git a/tests/ui/consts/const-err-late.stderr b/tests/ui/consts/const-err-late.stderr index 85bc56baed845..35c3d000117ef 100644 --- a/tests/ui/consts/const-err-late.stderr +++ b/tests/ui/consts/const-err-late.stderr @@ -27,6 +27,8 @@ note: erroneous constant encountered | LL | black_box((S::::FOO, S::::FOO)); | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr index c7aaee9427137..eea42c8ce451c 100644 --- a/tests/ui/consts/const-eval/issue-44578.stderr +++ b/tests/ui/consts/const-eval/issue-44578.stderr @@ -24,6 +24,7 @@ note: erroneous constant encountered LL | println!("{}", as Foo>::AMT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/nrvo.rs b/tests/ui/consts/const-eval/nrvo.rs index 1d2c6acc06cd5..22da96a3fc1ea 100644 --- a/tests/ui/consts/const-eval/nrvo.rs +++ b/tests/ui/consts/const-eval/nrvo.rs @@ -1,7 +1,8 @@ // run-pass // When the NRVO is applied, the return place (`_0`) gets treated like a normal local. For example, -// its address may be taken and it may be written to indirectly. Ensure that MIRI can handle this. +// its address may be taken and it may be written to indirectly. Ensure that the const-eval +// interpreter can handle this. #![feature(const_mut_refs)] diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr index 4706497dbc48f..50660664f87f8 100644 --- a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr +++ b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -17,6 +17,8 @@ note: erroneous constant encountered | LL | let _ = PrintName::VOID; | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 40fc4a876e9e5..8eee392d15cd5 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -40,6 +40,7 @@ help: the constant being evaluated | LL | const Y: u32 = simple_loop(35); | ^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:9:5 diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs index a94fcbbfa5634..c9799989ea835 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.rs +++ b/tests/ui/consts/const-eval/union-const-eval-field.rs @@ -1,5 +1,3 @@ -// only-x86_64 - type Field1 = i32; type Field2 = f32; type Field3 = i64; diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr index ce260300fc8c7..b299208ae8156 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.stderr +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,20 +1,22 @@ error[E0080]: evaluation of constant value failed - --> $DIR/union-const-eval-field.rs:28:37 + --> $DIR/union-const-eval-field.rs:26:37 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:31:5 + --> $DIR/union-const-eval-field.rs:29:5 | LL | FIELD3 | ^^^^^^ note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:31:5 + --> $DIR/union-const-eval-field.rs:29:5 | LL | FIELD3 | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs index 2b421f4c705ec..d45c32e170a6a 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.rs +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -15,7 +15,8 @@ const C: &[O] = &[O::None]; fn main() { let x = O::None; match &[x][..] { - C => (), + C => (), //~WARN: the type must implement `PartialEq` + //~| previously accepted _ => (), } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr new file mode 100644 index 0000000000000..9c80cb3a849c0 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `&[O]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +LL | C => (), + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `&[O]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +LL | C => (), + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index dc6b9a33197f1..df772740ab122 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -1,3 +1,5 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + // This test of structural match checking enumerates the different kinds of // const definitions, collecting cases where the const pattern is rejected. // @@ -78,9 +80,6 @@ fn main() { //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` //~| NOTE the traits must be derived //~| NOTE StructuralEq.html for details - //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralEq.html for details trait Trait: Sized { const ASSOC: Option; } impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index b6e439f21397f..72bb0aeafa466 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -1,5 +1,5 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:40:36 + --> $DIR/reject_non_structural.rs:42:36 | LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; | ^^^^ @@ -8,7 +8,7 @@ LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops" = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:46:28 + --> $DIR/reject_non_structural.rs:48:28 | LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; | ^^^^^ @@ -17,7 +17,7 @@ LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:53:27 + --> $DIR/reject_non_structural.rs:55:27 | LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops") = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:59:36 + --> $DIR/reject_non_structural.rs:61:36 | LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; | ^^^^^ @@ -35,7 +35,7 @@ LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoop = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:65:28 + --> $DIR/reject_non_structural.rs:67:28 | LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => p = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:71:36 + --> $DIR/reject_non_structural.rs:73:36 | LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; | ^^^^^ @@ -53,7 +53,7 @@ LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoop = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:77:33 + --> $DIR/reject_non_structural.rs:79:33 | LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; | ^^^^^^ @@ -62,16 +62,7 @@ LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:77:33 - | -LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; - | ^^^^^^ - | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:87:28 + --> $DIR/reject_non_structural.rs:86:28 | LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ @@ -80,7 +71,7 @@ LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => p = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:93:28 + --> $DIR/reject_non_structural.rs:92:28 | LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; | ^^^^^ @@ -89,7 +80,7 @@ LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/reject_non_structural.rs:99:29 + --> $DIR/reject_non_structural.rs:98:29 | LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; | ^^^^^^^ @@ -99,10 +90,10 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops") = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details note: the lint level is defined here - --> $DIR/reject_non_structural.rs:12:9 + --> $DIR/reject_non_structural.rs:14:9 | LL | #![warn(indirect_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted diff --git a/tests/ui/consts/enum-discr-type-err.stderr b/tests/ui/consts/enum-discr-type-err.stderr index 2f97582bea887..9a09d6a96f1a0 100644 --- a/tests/ui/consts/enum-discr-type-err.stderr +++ b/tests/ui/consts/enum-discr-type-err.stderr @@ -24,6 +24,7 @@ LL | | B = T, LL | | } | |_- in this macro invocation | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index bfebf66701bd9..3d82837d53040 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -10,6 +10,76 @@ error[E0635]: unknown feature `const_cmp` LL | #![feature(const_cmp)] | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:15:15 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:15:15 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:22:15 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:22:15 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:29:15 + | +LL | T: ~const FnOnce<()>, + | ^^^^^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:29:15 + | +LL | T: ~const FnOnce<()>, + | ^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:36:15 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:36:15 + | +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:50:15 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/fn_trait_refs.rs:50:15 + | +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index b6cf060e5aea8..0c57751cbfa4e 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -20,6 +20,8 @@ note: erroneous constant encountered | LL | let _: &'static _ = &C; | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index e3a3ef62c4acb..6c4d5882158d0 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -20,6 +20,8 @@ note: erroneous constant encountered | LL | let _: &'static _ = &C; | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/issue-102117.stderr b/tests/ui/consts/issue-102117.stderr index f42bcf90fb756..da92db87f1821 100644 --- a/tests/ui/consts/issue-102117.stderr +++ b/tests/ui/consts/issue-102117.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:19:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | pub fn new() -> &'static Self { | +++++++++ @@ -13,9 +16,13 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:19:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound | LL | pub fn new() -> &'static Self { | +++++++++ diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr index ce60aaa0797f8..405c2195dec4f 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.stderr +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -19,6 +19,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; | ^ | = help: consider extracting the value of the `static` to a `const`, and referring to that + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/consts/issue-67696-const-prop-ice.rs b/tests/ui/consts/issue-67696-const-prop-ice.rs index ad52608b3f46d..858035190ca21 100644 --- a/tests/ui/consts/issue-67696-const-prop-ice.rs +++ b/tests/ui/consts/issue-67696-const-prop-ice.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --emit=mir,link +// compile-flags: --emit=mir,link -Zmir-opt-level=4 // Checks that we don't ICE due to attempting to run const prop // on a function with unsatisifable 'where' clauses diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr index 274b1de7e7da1..b129aef3452e4 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr @@ -24,6 +24,8 @@ note: erroneous constant encountered | LL | let y = , String>>::F; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: skipping const checks | diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr index c8e4cab4e71bd..46408f6748d98 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr @@ -15,6 +15,8 @@ note: erroneous constant encountered | LL | let y = >::F; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr index f48e6c4ce51c6..c92824a0d1a17 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.stderr +++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr @@ -656,6 +656,8 @@ note: erroneous constant encountered | LL | dbg!(i32::CONSTANT); | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to previous error diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.rs b/tests/ui/consts/unstable-const-fn-in-libcore.rs index 61e28117ed455..b62a74039f6dd 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.rs +++ b/tests/ui/consts/unstable-const-fn-in-libcore.rs @@ -1,3 +1,5 @@ +// known-bug: #110395 +// FIXME check-pass // This is a non-regression test for const-qualification of unstable items in libcore // as explained in issue #67053. // const-qualification could miss some `const fn`s if they were unstable and the feature @@ -15,12 +17,12 @@ impl Opt { #[rustc_const_unstable(feature = "foo", issue = "none")] #[stable(feature = "rust1", since = "1.0.0")] const fn unwrap_or_else T>(self, f: F) -> T { - //~^ ERROR destructor of - //~| ERROR destructor of + //FIXME ~^ ERROR destructor of + //FIXME ~| ERROR destructor of match self { Opt::Some(t) => t, Opt::None => f(), - //~^ ERROR cannot call + //FIXME ~^ ERROR cannot call } } } diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 95d7b7e853766..b75f99a720f6e 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,34 +1,8 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/unstable-const-fn-in-libcore.rs:22:26 - | -LL | Opt::None => f(), - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { - | +++++++++++++++++++++++++++++ - -error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/unstable-const-fn-in-libcore.rs:17:60 - | -LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^ the destructor for this type cannot be evaluated in constant functions -... -LL | } - | - value is dropped here - -error[E0493]: destructor of `Opt` cannot be evaluated at compile-time - --> $DIR/unstable-const-fn-in-libcore.rs:17:54 +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/unstable-const-fn-in-libcore.rs:19:39 | LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^^^^ the destructor for this type cannot be evaluated in constant functions -... -LL | } - | - value is dropped here + | ^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/crate-loading/invalid-rlib.rs b/tests/ui/crate-loading/invalid-rlib.rs index aea861e3261b5..0997bee19bb6e 100644 --- a/tests/ui/crate-loading/invalid-rlib.rs +++ b/tests/ui/crate-loading/invalid-rlib.rs @@ -8,3 +8,4 @@ use ::foo; //~ ERROR invalid metadata files for crate `foo` //~| NOTE failed to mmap file //~^^ ERROR invalid metadata files for crate `foo` //~| NOTE failed to mmap file +//~| NOTE duplicate diagnostic diff --git a/tests/ui/crate-loading/invalid-rlib.stderr b/tests/ui/crate-loading/invalid-rlib.stderr index 3c0d23bf7b4cc..63bb1b95cbb78 100644 --- a/tests/ui/crate-loading/invalid-rlib.stderr +++ b/tests/ui/crate-loading/invalid-rlib.stderr @@ -13,6 +13,7 @@ LL | use ::foo; | ^^^ | = note: failed to mmap file 'auxiliary/libfoo.rlib' + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs index 9c3c359e395d5..fc3bbb88efe83 100644 --- a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs +++ b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs @@ -1,4 +1,4 @@ -// Verify that we do not trigger a LLVM assertion by creating zero-sized DWARF fragments. +// Verify that we do not trigger an LLVM assertion by creating zero-sized DWARF fragments. // // build-pass // compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates diff --git a/tests/ui/deduplicate-diagnostics.duplicate.stderr b/tests/ui/deduplicate-diagnostics.duplicate.stderr index cd4700c7a7c95..0544b993278d7 100644 --- a/tests/ui/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/deduplicate-diagnostics.duplicate.stderr @@ -15,12 +15,16 @@ error: cannot find derive macro `Unresolved` in this scope | LL | #[derive(Unresolved)] | ^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input --> $DIR/deduplicate-diagnostics.rs:8:8 | LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index 8b2b480d19586..383212ad9b4b8 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -16,25 +16,25 @@ error[E0541]: unknown meta item 'reason' LL | #[deprecated(since = "a", note = "a", reason)] | ^^^^^^ expected one of `since`, `note` -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:7:31 | LL | #[deprecated(since = "a", note)] | ^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:10:18 | LL | #[deprecated(since, note = "a")] | ^^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:13:31 | LL | #[deprecated(since = "a", note(b))] | ^^^^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:16:18 | LL | #[deprecated(since(b), note = "a")] @@ -70,5 +70,5 @@ LL | #[deprecated = "hello"] error: aborting due to 10 previous errors -Some errors have detailed explanations: E0538, E0541, E0551, E0565. +Some errors have detailed explanations: E0538, E0539, E0541, E0565. For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/derives/deriving-bounds.stderr b/tests/ui/derives/deriving-bounds.stderr index 74ca37287d232..4461652eb02e3 100644 --- a/tests/ui/derives/deriving-bounds.stderr +++ b/tests/ui/derives/deriving-bounds.stderr @@ -21,6 +21,7 @@ note: unsafe traits like `Sync` should be implemented explicitly | LL | #[derive(Sync)] | ^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `Send` in this scope --> $DIR/deriving-bounds.rs:1:10 @@ -45,6 +46,7 @@ note: unsafe traits like `Send` should be implemented explicitly | LL | #[derive(Send)] | ^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr index 053d34f68251a..28753b8f9f288 100644 --- a/tests/ui/derives/deriving-meta-unknown-trait.stderr +++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr @@ -15,6 +15,8 @@ LL | #[derive(Eqr)] --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named derive macro `Eq` defined here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/derives/deriving-primitive.stderr b/tests/ui/derives/deriving-primitive.stderr index ca64c9ee732cb..b39637825e56c 100644 --- a/tests/ui/derives/deriving-primitive.stderr +++ b/tests/ui/derives/deriving-primitive.stderr @@ -9,6 +9,8 @@ error: cannot find derive macro `FromPrimitive` in this scope | LL | #[derive(FromPrimitive)] | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index bb1b29ef248f0..bd39c91ffe88f 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -35,6 +35,8 @@ warning: malformed `on_unimplemented` attribute | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:14 @@ -60,6 +62,8 @@ warning: malformed `on_unimplemented` attribute | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:14 @@ -85,6 +89,8 @@ warning: malformed `on_unimplemented` attribute | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:15 diff --git a/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs new file mode 100644 index 0000000000000..4e2ee97403c5c --- /dev/null +++ b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs @@ -0,0 +1,6 @@ +#[derive(Default)] +pub struct B { + #[doc(hidden)] + pub hello: i32, + pub bye: i32, +} diff --git a/tests/ui/did_you_mean/bad-assoc-expr.stderr b/tests/ui/did_you_mean/bad-assoc-expr.stderr index c295cac9aa4b2..b83078e21b6a1 100644 --- a/tests/ui/did_you_mean/bad-assoc-expr.stderr +++ b/tests/ui/did_you_mean/bad-assoc-expr.stderr @@ -2,60 +2,104 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:3:5 | LL | [i32; 4]::clone(&a); - | ^^^^^^^^^^^^^^^ help: try: `<[i32; 4]>::clone` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[i32; 4]>::clone(&a); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:6:5 | LL | [i32]::as_ref(&a); - | ^^^^^^^^^^^^^ help: try: `<[i32]>::as_ref` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[i32]>::as_ref(&a); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:9:5 | LL | (u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:12:5 | LL | (u8, u8)::clone(&(0, 0)); - | ^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::clone` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8, u8)>::clone(&(0, 0)); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:15:6 | LL | &(u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | &<(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:18:10 | LL | 10 + (u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | 10 + <(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:32:13 | LL | let _ = ty!()::clone(&0); - | ^^^^^^^^^^^^ help: try: `::clone` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | let _ = ::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:34:5 | LL | ty!()::clone(&0); - | ^^^^^^^^^^^^ help: try: `::clone` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:23:19 | LL | ($ty: ty) => ($ty::clone(&0)) - | ^^^^^^^^^^ help: try: `<$ty>::clone` + | ^^^ ... LL | expr!(u8); | --------- in this macro invocation | = note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::clone(&0)) + | + + error: aborting due to 9 previous errors diff --git a/tests/ui/did_you_mean/bad-assoc-pat.stderr b/tests/ui/did_you_mean/bad-assoc-pat.stderr index 19d173f1b423c..8bdeb8ffdd0a8 100644 --- a/tests/ui/did_you_mean/bad-assoc-pat.stderr +++ b/tests/ui/did_you_mean/bad-assoc-pat.stderr @@ -2,42 +2,71 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:3:9 | LL | [u8]::AssocItem => {} - | ^^^^^^^^^^^^^^^ help: try: `<[u8]>::AssocItem` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[u8]>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:6:9 | LL | (u8, u8)::AssocItem => {} - | ^^^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocItem` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8, u8)>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:9:9 | LL | _::AssocItem => {} - | ^^^^^^^^^^^^ help: try: `<_>::AssocItem` + | ^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <_>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:14:10 | LL | &(u8,)::AssocItem => {} - | ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | &<(u8,)>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:32:9 | LL | ty!()::AssocItem => {} - | ^^^^^^^^^^^^^^^^ help: try: `::AssocItem` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:21:19 | LL | ($ty: ty) => ($ty::AssocItem) - | ^^^^^^^^^^^^^^ help: try: `<$ty>::AssocItem` + | ^^^ ... LL | pat!(u8) => {} | -------- in this macro invocation | = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::AssocItem) + | + + error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope --> $DIR/bad-assoc-pat.rs:3:15 diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 55096e95df7e0..efa6bb6682407 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -2,60 +2,104 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:1:10 | LL | type A = [u8; 4]::AssocTy; - | ^^^^^^^^^^^^^^^^ help: try: `<[u8; 4]>::AssocTy` + | ^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type A = <[u8; 4]>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:5:10 | LL | type B = [u8]::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<[u8]>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type B = <[u8]>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:9:10 | LL | type C = (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type C = <(u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:13:10 | LL | type D = (u8, u8)::AssocTy; - | ^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocTy` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type D = <(u8, u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:17:10 | LL | type E = _::AssocTy; - | ^^^^^^^^^^ help: try: `<_>::AssocTy` + | ^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type E = <_>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type F = &'static <(u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type G = ::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:46:10 | LL | type I = ty!()::AssocTy; - | ^^^^^^^^^^^^^^ help: try: `::AssocTy` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type I = ::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:39:19 | LL | ($ty: ty) => ($ty::AssocTy); - | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` + | ^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::AssocTy); + | + + error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs new file mode 100644 index 0000000000000..6040f3f30a7b5 --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs @@ -0,0 +1,38 @@ +// Regression test for issue #93210. + +// aux-crate:doc_hidden_fields=doc-hidden-fields.rs +// edition: 2021 + +#[derive(Default)] +pub struct A { + #[doc(hidden)] + pub hello: i32, + pub bye: i32, +} + +#[derive(Default)] +pub struct C { + pub hello: i32, + pub bye: i32, +} + +fn main() { + // We want to list the field `hello` despite being marked + // `doc(hidden)` because it's defined in this crate. + A::default().hey; + //~^ ERROR no field `hey` on type `A` + //~| NOTE unknown field + //~| NOTE available fields are: `hello`, `bye` + + // Here we want to hide the field `hello` since it's marked + // `doc(hidden)` and comes from an external crate. + doc_hidden_fields::B::default().hey; + //~^ ERROR no field `hey` on type `B` + //~| NOTE unknown field + //~| NOTE available fields are: `bye` + + C::default().hey; + //~^ ERROR no field `hey` on type `C` + //~| NOTE unknown field + //~| NOTE available fields are: `hello`, `bye` +} diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr new file mode 100644 index 0000000000000..b7fe3b79b475b --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr @@ -0,0 +1,27 @@ +error[E0609]: no field `hey` on type `A` + --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18 + | +LL | A::default().hey; + | ^^^ unknown field + | + = note: available fields are: `hello`, `bye` + +error[E0609]: no field `hey` on type `B` + --> $DIR/dont-suggest-doc-hidden-fields.rs:29:37 + | +LL | doc_hidden_fields::B::default().hey; + | ^^^ unknown field + | + = note: available fields are: `bye` + +error[E0609]: no field `hey` on type `C` + --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18 + | +LL | C::default().hey; + | ^^^ unknown field + | + = note: available fields are: `hello`, `bye` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs new file mode 100644 index 0000000000000..fb7040b2df095 --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs @@ -0,0 +1,47 @@ +// Regression test for issue #116334. +// Don't include hygienic fields from different syntax contexts in +// the list of available or similarly named fields. + +#![feature(decl_macro)] + +macro compound($Ty:ident) { + #[derive(Default)] + struct $Ty { + field: u32, // field `field` is hygienic + } +} + +macro component($Ty:ident) { + struct $Ty(u64); // field `0` is hygienic (but still accessible via the constructor) +} + +compound! { Compound } +component! { Component } + +fn main() { + let ty = Compound::default(); + + let _ = ty.field; //~ ERROR no field `field` on type `Compound` + let _ = ty.fieeld; //~ ERROR no field `fieeld` on type `Compound` + + let Compound { field } = ty; + //~^ ERROR struct `Compound` does not have a field named `field` + //~| ERROR pattern requires `..` due to inaccessible fields + //~| HELP ignore the inaccessible and unused fields + + let ty = Component(90); + + let _ = ty.0; //~ ERROR no field `0` on type `Component` +} + +environment!(); + +macro environment() { + struct Crate { field: () } + + // Here, we do want to suggest `field` even though it's hygienic + // precisely because they come from the same syntax context. + const CRATE: Crate = Crate { fiel: () }; + //~^ ERROR struct `Crate` has no field named `fiel` + //~| HELP a field with a similar name exists +} diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr new file mode 100644 index 0000000000000..7066d29760e7c --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -0,0 +1,50 @@ +error[E0560]: struct `Crate` has no field named `fiel` + --> $DIR/dont-suggest-hygienic-fields.rs:44:34 + | +LL | environment!(); + | -------------- in this macro invocation +... +LL | const CRATE: Crate = Crate { fiel: () }; + | ^^^^ help: a field with a similar name exists: `field` + | + = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `field` on type `Compound` + --> $DIR/dont-suggest-hygienic-fields.rs:24:16 + | +LL | let _ = ty.field; + | ^^^^^ unknown field + +error[E0609]: no field `fieeld` on type `Compound` + --> $DIR/dont-suggest-hygienic-fields.rs:25:16 + | +LL | let _ = ty.fieeld; + | ^^^^^^ unknown field + +error[E0026]: struct `Compound` does not have a field named `field` + --> $DIR/dont-suggest-hygienic-fields.rs:27:20 + | +LL | let Compound { field } = ty; + | ^^^^^ struct `Compound` does not have this field + +error: pattern requires `..` due to inaccessible fields + --> $DIR/dont-suggest-hygienic-fields.rs:27:9 + | +LL | let Compound { field } = ty; + | ^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let Compound { field, .. } = ty; + | ++++ + +error[E0609]: no field `0` on type `Component` + --> $DIR/dont-suggest-hygienic-fields.rs:34:16 + | +LL | let _ = ty.0; + | ^ unknown field + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0026, E0560, E0609. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs deleted file mode 100644 index 0efc7daa3e17b..0000000000000 --- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[derive(Default)] -pub struct A { - #[doc(hidden)] - pub hello: i32, - pub bye: i32, -} - -#[derive(Default)] -pub struct B { - pub hello: i32, - pub bye: i32, -} - -fn main() { - A::default().hey; - //~^ ERROR no field `hey` on type `A` - //~| NOTE unknown field - //~| NOTE available fields are: `bye` - - B::default().hey; - //~^ ERROR no field `hey` on type `B` - //~| NOTE unknown field - //~| NOTE available fields are: `hello`, `bye` -} diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr deleted file mode 100644 index 784986d3b95fb..0000000000000 --- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0609]: no field `hey` on type `A` - --> $DIR/issue-93210-ignore-doc-hidden.rs:15:18 - | -LL | A::default().hey; - | ^^^ unknown field - | - = note: available fields are: `bye` - -error[E0609]: no field `hey` on type `B` - --> $DIR/issue-93210-ignore-doc-hidden.rs:20:18 - | -LL | B::default().hey; - | ^^^ unknown field - | - = note: available fields are: `hello`, `bye` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index 6bafff9192a36..931786672145b 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -50,6 +50,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn function(x: &dyn SomeTrait, y: Box) { @@ -63,6 +64,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn function(x: &dyn SomeTrait, y: Box) { @@ -76,6 +78,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn function(x: &SomeTrait, y: Box) { @@ -89,6 +92,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn function(x: &SomeTrait, y: Box) { diff --git a/tests/ui/entry-point/auxiliary/bad_main_functions.rs b/tests/ui/entry-point/auxiliary/bad_main_functions.rs new file mode 100644 index 0000000000000..4649be99e6f27 --- /dev/null +++ b/tests/ui/entry-point/auxiliary/bad_main_functions.rs @@ -0,0 +1,2 @@ +pub fn boilerplate(x: u8) {} +//~^ ERROR: `main` function has wrong type [E0580] diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs new file mode 100644 index 0000000000000..0a115dd3b0810 --- /dev/null +++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs @@ -0,0 +1,6 @@ +// aux-build:bad_main_functions.rs + +#![feature(imported_main)] + +extern crate bad_main_functions; +pub use bad_main_functions::boilerplate as main; diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr new file mode 100644 index 0000000000000..3c68933101c87 --- /dev/null +++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr @@ -0,0 +1,12 @@ +error[E0580]: `main` function has wrong type + --> $DIR/auxiliary/bad_main_functions.rs:1:1 + | +LL | pub fn boilerplate(x: u8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected signature `fn()` + found signature `fn(u8)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs index a2ec932c12455..97ebcff99dc94 100644 --- a/tests/ui/error-codes/E0094.rs +++ b/tests/ui/error-codes/E0094.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { #[rustc_safe_intrinsic] diff --git a/tests/ui/error-codes/E0132.stderr b/tests/ui/error-codes/E0132.stderr index c21363756b3e6..d4ddc07b52112 100644 --- a/tests/ui/error-codes/E0132.stderr +++ b/tests/ui/error-codes/E0132.stderr @@ -1,8 +1,8 @@ -error[E0132]: start function is not allowed to have type parameters +error[E0132]: `#[start]` function is not allowed to have type parameters --> $DIR/E0132.rs:4:5 | LL | fn f< T >() {} - | ^^^^^ start function cannot have type parameters + | ^^^^^ `#[start]` function cannot have type parameters error: aborting due to previous error diff --git a/tests/ui/error-codes/E0282.rs b/tests/ui/error-codes/E0282.rs index f1f93b3aed615..5bc29cda9ea3c 100644 --- a/tests/ui/error-codes/E0282.rs +++ b/tests/ui/error-codes/E0282.rs @@ -1,4 +1,4 @@ fn main() { - let x = "hello".chars().rev().collect(); + let x; //~^ ERROR E0282 } diff --git a/tests/ui/error-codes/E0282.stderr b/tests/ui/error-codes/E0282.stderr index 892d3a81f27f9..58332454a3753 100644 --- a/tests/ui/error-codes/E0282.stderr +++ b/tests/ui/error-codes/E0282.stderr @@ -1,13 +1,13 @@ error[E0282]: type annotations needed --> $DIR/E0282.rs:2:9 | -LL | let x = "hello".chars().rev().collect(); +LL | let x; | ^ | help: consider giving `x` an explicit type | -LL | let x: Vec<_> = "hello".chars().rev().collect(); - | ++++++++ +LL | let x: /* Type */; + | ++++++++++++ error: aborting due to previous error diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr index 187b775f92dc0..141abed6032eb 100644 --- a/tests/ui/error-codes/E0308.stderr +++ b/tests/ui/error-codes/E0308.stderr @@ -1,11 +1,11 @@ error[E0308]: intrinsic has wrong type - --> $DIR/E0308.rs:6:5 + --> $DIR/E0308.rs:6:20 | LL | fn size_of(); - | ^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | ^ expected `usize`, found `()` | - = note: expected fn pointer `extern "rust-intrinsic" fn()` - found fn pointer `extern "rust-intrinsic" fn() -> usize` + = note: expected signature `extern "rust-intrinsic" fn() -> usize` + found signature `extern "rust-intrinsic" fn()` error: aborting due to previous error diff --git a/tests/ui/error-codes/E0311.fixed b/tests/ui/error-codes/E0311.fixed index 4410a4d707af4..09ceecd0666cd 100644 --- a/tests/ui/error-codes/E0311.fixed +++ b/tests/ui/error-codes/E0311.fixed @@ -2,7 +2,7 @@ #![allow(warnings)] -fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { +fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { with_restriction::(x) //~ ERROR E0311 } diff --git a/tests/ui/error-codes/E0311.stderr b/tests/ui/error-codes/E0311.stderr index b0e6dd1e2727c..96546b83f2f93 100644 --- a/tests/ui/error-codes/E0311.stderr +++ b/tests/ui/error-codes/E0311.stderr @@ -1,23 +1,15 @@ error[E0311]: the parameter type `T` may not live long enough --> $DIR/E0311.rs:6:5 | -LL | with_restriction::(x) - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `T` must be valid for the anonymous lifetime defined here... - --> $DIR/E0311.rs:5:25 - | LL | fn no_restriction(x: &()) -> &() { - | ^^^ -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/E0311.rs:6:5 - | + | --- the parameter type `T` must be valid for the anonymous lifetime defined here... LL | with_restriction::(x) - | ^^^^^^^^^^^^^^^^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | -LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { - | +++ ++++ ++ +LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + | +++ ++++ ++ ++ error: aborting due to previous error diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 68e15e6f8fe81..49ec0bce44169 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -1,8 +1,11 @@ -error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found +error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0374.rs:8:1 | -LL | impl CoerceUnsized> for Foo - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl CoerceUnsized> for Foo +LL | | where T: CoerceUnsized {} + | |_____________________________^ + | + = note: expected a single field to be coerced, none found error: aborting due to previous error diff --git a/tests/ui/error-codes/E0377.stderr b/tests/ui/error-codes/E0377.stderr index bf7d8c8d39d2a..9cb11e5a3d3a5 100644 --- a/tests/ui/error-codes/E0377.stderr +++ b/tests/ui/error-codes/E0377.stderr @@ -1,8 +1,10 @@ -error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with the same definition; expected `Foo`, found `Bar` +error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0377.rs:12:1 | LL | impl CoerceUnsized> for Foo where T: CoerceUnsized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected coercion between the same definition; expected `Foo`, found `Bar` error: aborting due to previous error diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index 928c8d11d2030..0a069e8d35063 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -32,12 +32,18 @@ LL | fn helper(sel: &Self) -> u8 { | use of generic parameter from outer item | refer to the type directly here instead -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/E0401.rs:11:5 | LL | bfnr(x); - | ^^^^ cannot infer type of the type parameter `U` declared on the function `bfnr` + | ^^^^ cannot infer type of the type parameter `V` declared on the function `bfnr` + | + = note: cannot satisfy `_: Baz<_>` +note: required by a bound in `bfnr` + --> $DIR/E0401.rs:4:19 | +LL | fn bfnr, W: Fn()>(y: T) { + | ^^^^^^ required by this bound in `bfnr` help: consider specifying the generic arguments | LL | bfnr::(x); @@ -66,5 +72,5 @@ LL | bfnr::(x); error: aborting due to 5 previous errors -Some errors have detailed explanations: E0282, E0283, E0401. -For more information about an error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0283, E0401. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr index f67b740ffe23b..986c135ed89cd 100644 --- a/tests/ui/error-codes/E0452.stderr +++ b/tests/ui/error-codes/E0452.stderr @@ -9,18 +9,24 @@ error[E0452]: malformed lint attribute input | LL | #![allow(foo = "")] | ^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] | ^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] | ^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/error-codes/E0453.stderr b/tests/ui/error-codes/E0453.stderr index f982ed26f5c0b..bb2c39298c080 100644 --- a/tests/ui/error-codes/E0453.stderr +++ b/tests/ui/error-codes/E0453.stderr @@ -15,6 +15,8 @@ LL | #![forbid(non_snake_case)] LL | LL | #[allow(non_snake_case)] | ^^^^^^^^^^^^^^ overruled by previous forbid + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0476.stderr b/tests/ui/error-codes/E0476.stderr index a4bb26532a24f..0378ac6e8ec91 100644 --- a/tests/ui/error-codes/E0476.stderr +++ b/tests/ui/error-codes/E0476.stderr @@ -2,7 +2,7 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T @@ -12,7 +12,7 @@ error[E0476]: lifetime of the source pointer does not outlive lifetime bound of --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here --> $DIR/E0476.rs:9:6 diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr index 60ecec7cdd7c5..b6b5cd5c3d3e6 100644 --- a/tests/ui/error-codes/E0602.stderr +++ b/tests/ui/error-codes/E0602.stderr @@ -6,10 +6,12 @@ warning[E0602]: unknown lint: `bogus` warning[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/error-codes/E0647.stderr b/tests/ui/error-codes/E0647.stderr index 08cedfaef04ce..9d1ab967127ad 100644 --- a/tests/ui/error-codes/E0647.stderr +++ b/tests/ui/error-codes/E0647.stderr @@ -1,8 +1,8 @@ -error[E0647]: start function is not allowed to have a `where` clause +error[E0647]: `#[start]` function is not allowed to have a `where` clause --> $DIR/E0647.rs:7:50 | LL | fn start(_: isize, _: *const *const u8) -> isize where (): Copy { - | ^^^^^^^^^^^^^^ start function cannot have a `where` clause + | ^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause error: aborting due to previous error diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr index e302f406d02b0..685bd7175e3ff 100644 --- a/tests/ui/error-codes/E0719.stderr +++ b/tests/ui/error-codes/E0719.stderr @@ -13,6 +13,8 @@ LL | trait Foo: Iterator {} | ---------- ^^^^^^^^^^ re-bound here | | | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/E0719.rs:7:42 diff --git a/tests/ui/error-codes/E0767.stderr b/tests/ui/error-codes/E0767.stderr index ee85247301c9c..4b09008f9a0f9 100644 --- a/tests/ui/error-codes/E0767.stderr +++ b/tests/ui/error-codes/E0767.stderr @@ -19,7 +19,7 @@ LL | | } | |_________^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/E0767.rs:3:9: 3:11]` + found closure `{closure@$DIR/E0767.rs:3:9: 3:11}` error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0789.stderr b/tests/ui/error-codes/E0789.stderr index faab92bae035d..6df9daafec76d 100644 --- a/tests/ui/error-codes/E0789.stderr +++ b/tests/ui/error-codes/E0789.stderr @@ -9,6 +9,8 @@ error[E0789]: `rustc_allowed_through_unstable_modules` attribute must be paired | LL | struct Foo; | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs new file mode 100644 index 0000000000000..7f351e48b6fa1 --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs @@ -0,0 +1,10 @@ +// compile-flags: --extern=my-awesome-library=libawesome.rlib +// error-pattern: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier +// error-pattern: consider replacing the dashes with underscores: `my_awesome_library` + +// In a sense, this is a regression test for issue #113035. We no longer suggest +// `pub use my-awesome-library::*;` (sic!) as we outright ban this crate name. + +pub use my_awesome_library::*; + +fn main() {} diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.stderr b/tests/ui/extern-flag/invalid-crate-name-dashed.stderr new file mode 100644 index 0000000000000..5da1c4bb20a37 --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name-dashed.stderr @@ -0,0 +1,4 @@ +error: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier + | + = help: consider replacing the dashes with underscores: `my_awesome_library` + diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs new file mode 100644 index 0000000000000..ec4a85820d122 --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs @@ -0,0 +1,4 @@ +// compile-flags: --extern čɍαţē=libnon_ascii.rlib +// error-pattern: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier + +fn main() {} diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr b/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr new file mode 100644 index 0000000000000..6b38dcd01e0c3 --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr @@ -0,0 +1,2 @@ +error: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier + diff --git a/tests/ui/extern-flag/invalid-crate-name.rs b/tests/ui/extern-flag/invalid-crate-name.rs new file mode 100644 index 0000000000000..a26b5dd4635ff --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name.rs @@ -0,0 +1,4 @@ +// compile-flags: --extern=?#1%$ +// error-pattern: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier + +fn main() {} diff --git a/tests/ui/extern-flag/invalid-crate-name.stderr b/tests/ui/extern-flag/invalid-crate-name.stderr new file mode 100644 index 0000000000000..e2f83160db904 --- /dev/null +++ b/tests/ui/extern-flag/invalid-crate-name.stderr @@ -0,0 +1,2 @@ +error: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier + diff --git a/tests/ui/extern/extern-main-fn.stderr b/tests/ui/extern/extern-main-fn.stderr index 136c957538248..846102670a83f 100644 --- a/tests/ui/extern/extern-main-fn.stderr +++ b/tests/ui/extern/extern-main-fn.stderr @@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type LL | extern "C" fn main() {} | ^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn | - = note: expected fn pointer `fn()` - found fn pointer `extern "C" fn()` + = note: expected signature `fn()` + found signature `extern "C" fn()` error: aborting due to previous error diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs index a72aa4171a103..99e9801fd4010 100644 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ b/tests/ui/extern/extern-with-type-bounds.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { // Real example from libcore diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr index d8f089a28b7e1..13b9b84f0be4e 100644 --- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index 49fb10e602959..152c7a8de66a1 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -54,20 +54,20 @@ fn _rpit_dyn() -> Box> { Box::new(S1) } const _cdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // const _cdef_dyn: &dyn Tr1 = &S1; static _sdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // static _sdef_dyn: &dyn Tr1 = &S1; fn main() { let _: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable - //~| ERROR `impl Trait` only allowed in function and inherent method return types + //~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // let _: &dyn Tr1 = &S1; } diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 4233a8af9b6a6..f2bceda9bea71 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -115,19 +115,19 @@ LL | let _: impl Tr1 = S1; = note: see issue #52662 for more information = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/feature-gate-associated_type_bounds.rs:55:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/feature-gate-associated_type_bounds.rs:61:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/feature-gate-associated_type_bounds.rs:68:12 | LL | let _: impl Tr1 = S1; diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs index 0db8088f7eea4..1b9530fa82f38 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -1,6 +1,6 @@ fn f() -> impl Fn() -> impl Sized { || () } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return fn g() -> &'static dyn Fn() -> impl Sized { &|| () } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr index c8c3e13d7fc5a..f0c0cd040e03c 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 | LL | fn f() -> impl Fn() -> impl Sized { || () } @@ -7,7 +7,7 @@ LL | fn f() -> impl Fn() -> impl Sized { || () } = note: see issue #99697 for more information = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr index 12793c7a28fca..6d49b7ed2cd04 100644 --- a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr +++ b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr @@ -15,6 +15,7 @@ LL | #![warn(nonstandard_style, reason = "the standard should be respected")] | = note: see issue #54503 for more information = help: add `#![feature(lint_reasons)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr index 1f725f3541778..5e14bf6397fe6 100644 --- a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr +++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr @@ -25,6 +25,7 @@ LL | #![deny(multiple_supertrait_upcastable)] | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `multiple_supertrait_upcastable` --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1 @@ -34,6 +35,7 @@ LL | #![warn(multiple_supertrait_upcastable)] | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `multiple_supertrait_upcastable` --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1 @@ -43,6 +45,7 @@ LL | #![deny(multiple_supertrait_upcastable)] | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `multiple_supertrait_upcastable` --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1 @@ -52,6 +55,7 @@ LL | #![warn(multiple_supertrait_upcastable)] | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 6 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index fb39c404c207e..1c14622d6378b 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -38,6 +38,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 @@ -58,6 +59,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 @@ -68,6 +70,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 @@ -78,6 +81,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 @@ -88,6 +92,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 @@ -98,6 +103,7 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0004]: non-exhaustive patterns: `Foo::C` not covered --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11 diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.rs b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.rs new file mode 100644 index 0000000000000..0648ce0ee20e8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.rs @@ -0,0 +1,10 @@ +// force-host +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::Literal; + +fn test() { + Literal::byte_character(b'a'); //~ ERROR use of unstable library feature 'proc_macro_byte_character' +} diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr new file mode 100644 index 0000000000000..0069153893886 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'proc_macro_byte_character' + --> $DIR/feature-gate-proc_macro_byte_character.rs:9:5 + | +LL | Literal::byte_character(b'a'); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #115268 for more information + = help: add `#![feature(proc_macro_byte_character)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs index 637765fff11e4..a8d6365ca79ac 100644 --- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -5,14 +5,14 @@ #![feature(async_fn_in_trait)] trait Foo { - fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return - fn baz() -> Box; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return + fn baz() -> Box; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return } // Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also // feature-gate-async_fn_in_trait.rs) trait AsyncFoo { - async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr index 0082b6fafee8f..86f138fabdb9d 100644 --- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17 | LL | fn bar() -> impl Sized; @@ -7,7 +7,7 @@ LL | fn bar() -> impl Sized; = note: see issue #91611 for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21 | LL | fn baz() -> Box; @@ -16,7 +16,7 @@ LL | fn baz() -> Box; = note: see issue #91611 for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23 | LL | async fn bar() -> impl Sized; diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 1bdb2574eadc3..f6230b7646358 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -1,5 +1,5 @@ error[E0658]: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo>() {} | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn foo>() {} = help: add `#![feature(return_type_notation)]` to the crate attributes to enable error: parenthesized generic arguments cannot be used in associated type constraints - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo>() {} | ^-- @@ -16,7 +16,7 @@ LL | fn foo>() {} | help: remove these parentheses error[E0220]: associated type `m` not found for `Trait` - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo>() {} | ^ associated type `m` not found diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr index dd6ebb6103862..c7f52d7cddc20 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr @@ -1,5 +1,5 @@ warning: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo>() {} | ^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index ae12495b5dc68..c0c285cef3cb1 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -7,6 +7,7 @@ #![feature(async_fn_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn m(); } diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr index 751da87cc0d00..1e6d762a54060 100644 --- a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr +++ b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr @@ -28,6 +28,7 @@ LL | #![deny(fuzzy_provenance_casts)] = note: the `fuzzy_provenance_casts` lint is unstable = note: see issue #95228 for more information = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `lossy_provenance_casts` --> $DIR/feature-gate-strict_provenance.rs:7:1 @@ -38,6 +39,7 @@ LL | #![deny(lossy_provenance_casts)] = note: the `lossy_provenance_casts` lint is unstable = note: see issue #95228 for more information = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `fuzzy_provenance_casts` --> $DIR/feature-gate-strict_provenance.rs:3:1 @@ -48,6 +50,7 @@ LL | #![deny(fuzzy_provenance_casts)] = note: the `fuzzy_provenance_casts` lint is unstable = note: see issue #95228 for more information = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `lossy_provenance_casts` --> $DIR/feature-gate-strict_provenance.rs:7:1 @@ -58,6 +61,7 @@ LL | #![deny(lossy_provenance_casts)] = note: the `lossy_provenance_casts` lint is unstable = note: see issue #95228 for more information = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 6 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr index b4d6aa658e1bd..562aa478a93eb 100644 --- a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr @@ -16,6 +16,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `test_unstable_lint` --> $DIR/feature-gate-test_unstable_lint.rs:4:1 @@ -25,6 +26,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr index 4349fea6f8960..2614f2b3c35de 100644 --- a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr +++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr @@ -18,6 +18,7 @@ LL | #![warn(unnameable_types)] = note: the `unnameable_types` lint is unstable = note: see issue #48054 for more information = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `unnameable_types` --> $DIR/feature-gate-type_privacy_lints.rs:3:1 @@ -28,6 +29,7 @@ LL | #![warn(unnameable_types)] = note: the `unnameable_types` lint is unstable = note: see issue #48054 for more information = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr index ab16591734471..1e47259cb7ed5 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr @@ -9,6 +9,8 @@ error: cannot find derive macro `x3300` in this scope | LL | #[derive(x3300)] | ^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `x3300` in this scope --> $DIR/issue-43106-gating-of-derive-2.rs:9:14 @@ -21,6 +23,8 @@ error: cannot find derive macro `x3300` in this scope | LL | #[derive(x3300)] | ^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `x3300` in this scope --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 @@ -33,6 +37,8 @@ error: cannot find derive macro `x3300` in this scope | LL | #[derive(x3300)] | ^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/fn/bad-main.stderr b/tests/ui/fn/bad-main.stderr index 675b66d057838..65140a0794f84 100644 --- a/tests/ui/fn/bad-main.stderr +++ b/tests/ui/fn/bad-main.stderr @@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type LL | fn main(x: isize) { } | ^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn()` - found fn pointer `fn(isize)` + = note: expected signature `fn()` + found signature `fn(isize)` error: aborting due to previous error diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index 458756a3dcd96..3f6401b9f7a4d 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -2,14 +2,16 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13 | LL | impl<'a, T> Trait<'a> for T { - | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | -- ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... | note: ...that is required by this bound --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18 | LL | trait Trait<'a>: 'a { | ^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a> for T { | ++++ diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 0955efdbb7379..28dbdf4c374c0 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -44,12 +44,6 @@ LL | for item in *things { *item = 0 } = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature -error: the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed - --> $DIR/issue-20605.rs:5:17 - | -LL | for item in *things { *item = 0 } - | ^^^^^^^ - error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time --> $DIR/issue-20605.rs:5:5 | @@ -60,6 +54,12 @@ LL | for item in *things { *item = 0 } note: required by a bound in `None` --> $SRC_DIR/core/src/option.rs:LL:COL +error: the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed + --> $DIR/issue-20605.rs:5:17 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^ + error[E0614]: type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced --> $DIR/issue-20605.rs:5:27 | diff --git a/tests/ui/foreign/foreign-fn-linkname.rs b/tests/ui/foreign/foreign-fn-linkname.rs index f6d820594f966..d1d6e703e3dd4 100644 --- a/tests/ui/foreign/foreign-fn-linkname.rs +++ b/tests/ui/foreign/foreign-fn-linkname.rs @@ -2,6 +2,9 @@ // ignore-wasm32-bare no libc to test ffi with // ignore-sgx no libc +// Ensure no false positive on "unused extern crate" lint +#![deny(unused_extern_crates)] + #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/functions-closures/fn-help-with-err.stderr b/tests/ui/functions-closures/fn-help-with-err.stderr index da081eb435584..e5fe4611434ea 100644 --- a/tests/ui/functions-closures/fn-help-with-err.stderr +++ b/tests/ui/functions-closures/fn-help-with-err.stderr @@ -4,11 +4,11 @@ error[E0425]: cannot find value `oops` in this scope LL | let arc = std::sync::Arc::new(oops); | ^^^^ not found in this scope -error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:18:36: 18:38]>` in the current scope +error[E0599]: no method named `bar` found for struct `Arc<{closure@$DIR/fn-help-with-err.rs:18:36: 18:38}>` in the current scope --> $DIR/fn-help-with-err.rs:19:10 | LL | arc2.bar(); - | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:18:36]>` + | ^^^ method not found in `Arc<{closure@fn-help-with-err.rs:18:36}>` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `bar`, perhaps you need to implement it diff --git a/tests/ui/generator/addassign-yield.rs b/tests/ui/generator/addassign-yield.rs index 7211367afeee6..66f22bf31fc40 100644 --- a/tests/ui/generator/addassign-yield.rs +++ b/tests/ui/generator/addassign-yield.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // run-pass // Regression test for broken MIR error (#61442) // Due to the two possible evaluation orders for diff --git a/tests/ui/generator/auto-trait-regions.drop_tracking.stderr b/tests/ui/generator/auto-trait-regions.drop_tracking.stderr deleted file mode 100644 index b2a5b92ed0f97..0000000000000 --- a/tests/ui/generator/auto-trait-regions.drop_tracking.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:24 - | -LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -... -LL | assert_foo(a); - | - borrow later used here - | -help: consider using a `let` binding to create a longer lived value - | -LL ~ let binding = true; -LL ~ let a = A(&mut binding, &mut true, No); - | - -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:35 - | -LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -... -LL | assert_foo(a); - | - borrow later used here - | -help: consider using a `let` binding to create a longer lived value - | -LL ~ let binding = true; -LL ~ let a = A(&mut true, &mut binding, No); - | - -error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:34:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough - | - = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... - = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` - -error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:54:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough - | - = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr b/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr deleted file mode 100644 index b2a5b92ed0f97..0000000000000 --- a/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:24 - | -LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -... -LL | assert_foo(a); - | - borrow later used here - | -help: consider using a `let` binding to create a longer lived value - | -LL ~ let binding = true; -LL ~ let a = A(&mut binding, &mut true, No); - | - -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:35 - | -LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -... -LL | assert_foo(a); - | - borrow later used here - | -help: consider using a `let` binding to create a longer lived value - | -LL ~ let binding = true; -LL ~ let a = A(&mut true, &mut binding, No); - | - -error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:34:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough - | - = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... - = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` - -error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:54:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough - | - = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generator/auto-trait-regions.rs b/tests/ui/generator/auto-trait-regions.rs index 350f3cc34ce52..aa4218e13a46b 100644 --- a/tests/ui/generator/auto-trait-regions.rs +++ b/tests/ui/generator/auto-trait-regions.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(generators)] #![feature(auto_traits)] #![feature(negative_impls)] diff --git a/tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr b/tests/ui/generator/auto-trait-regions.stderr similarity index 92% rename from tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr rename to tests/ui/generator/auto-trait-regions.stderr index b2a5b92ed0f97..a9a0bde2ba019 100644 --- a/tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr +++ b/tests/ui/generator/auto-trait-regions.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:24 + --> $DIR/auto-trait-regions.rs:45:24 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -16,7 +16,7 @@ LL ~ let a = A(&mut binding, &mut true, No); | error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:48:35 + --> $DIR/auto-trait-regions.rs:45:35 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -33,7 +33,7 @@ LL ~ let a = A(&mut true, &mut binding, No); | error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:34:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough @@ -42,7 +42,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:54:5 + --> $DIR/auto-trait-regions.rs:51:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough diff --git a/tests/ui/generator/borrowing.drop_tracking.stderr b/tests/ui/generator/borrowing.drop_tracking.stderr deleted file mode 100644 index 96e3c327f8b31..0000000000000 --- a/tests/ui/generator/borrowing.drop_tracking.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:13:33 - | -LL | let _b = { - | -- borrow later stored here -LL | let a = 3; -LL | Pin::new(&mut || yield &a).resume(()) - | -- ^ borrowed value does not live long enough - | | - | value captured here by generator -LL | -LL | }; - | - `a` dropped here while still borrowed - -error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:20:20 - | -LL | let _b = { - | -- borrow later stored here -LL | let a = 3; -LL | || { - | -- value captured here by generator -LL | yield &a - | ^ borrowed value does not live long enough -... -LL | }; - | - `a` dropped here while still borrowed - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generator/borrowing.no_drop_tracking.stderr b/tests/ui/generator/borrowing.no_drop_tracking.stderr deleted file mode 100644 index 96e3c327f8b31..0000000000000 --- a/tests/ui/generator/borrowing.no_drop_tracking.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:13:33 - | -LL | let _b = { - | -- borrow later stored here -LL | let a = 3; -LL | Pin::new(&mut || yield &a).resume(()) - | -- ^ borrowed value does not live long enough - | | - | value captured here by generator -LL | -LL | }; - | - `a` dropped here while still borrowed - -error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:20:20 - | -LL | let _b = { - | -- borrow later stored here -LL | let a = 3; -LL | || { - | -- value captured here by generator -LL | yield &a - | ^ borrowed value does not live long enough -... -LL | }; - | - `a` dropped here while still borrowed - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generator/borrowing.rs b/tests/ui/generator/borrowing.rs index 29f39437f8f55..d36592583cdc5 100644 --- a/tests/ui/generator/borrowing.rs +++ b/tests/ui/generator/borrowing.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - #![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/tests/ui/generator/borrowing.drop_tracking_mir.stderr b/tests/ui/generator/borrowing.stderr similarity index 96% rename from tests/ui/generator/borrowing.drop_tracking_mir.stderr rename to tests/ui/generator/borrowing.stderr index 8fbad276db441..03a69fe362313 100644 --- a/tests/ui/generator/borrowing.drop_tracking_mir.stderr +++ b/tests/ui/generator/borrowing.stderr @@ -1,5 +1,5 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:13:33 + --> $DIR/borrowing.rs:9:33 | LL | Pin::new(&mut || yield &a).resume(()) | ----------^ @@ -21,7 +21,7 @@ LL | let x = Pin::new(&mut || yield &a).resume(()); x | +++++++ +++ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:20:20 + --> $DIR/borrowing.rs:16:20 | LL | let _b = { | -- borrow later stored here diff --git a/tests/ui/generator/clone-impl-async.stderr b/tests/ui/generator/clone-impl-async.stderr index 9854728876f64..d172dff3abd22 100644 --- a/tests/ui/generator/clone-impl-async.stderr +++ b/tests/ui/generator/clone-impl-async.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Copy` is not satisfied --> $DIR/clone-impl-async.rs:17:16 | LL | check_copy(&inner_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]` + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}` | | | required by a bound introduced by this call | @@ -12,11 +12,11 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Clone` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Clone` is not satisfied --> $DIR/clone-impl-async.rs:19:17 | LL | check_clone(&inner_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]` + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}` | | | required by a bound introduced by this call | @@ -26,11 +26,11 @@ note: required by a bound in `check_clone` LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Copy` is not satisfied --> $DIR/clone-impl-async.rs:26:16 | LL | check_copy(&outer_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]` + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}` | | | required by a bound introduced by this call | @@ -40,11 +40,11 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Clone` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Clone` is not satisfied --> $DIR/clone-impl-async.rs:28:17 | LL | check_clone(&outer_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]` + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}` | | | required by a bound introduced by this call | @@ -54,11 +54,11 @@ note: required by a bound in `check_clone` LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Copy` is not satisfied --> $DIR/clone-impl-async.rs:32:16 | LL | check_copy(&maybe_copy_clone); - | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]` + | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}` | | | required by a bound introduced by this call | @@ -68,11 +68,11 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Clone` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Clone` is not satisfied --> $DIR/clone-impl-async.rs:34:17 | LL | check_clone(&maybe_copy_clone); - | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]` + | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}` | | | required by a bound introduced by this call | diff --git a/tests/ui/generator/clone-impl-static.stderr b/tests/ui/generator/clone-impl-static.stderr index cbadf6f156a9f..8b51824c7d25a 100644 --- a/tests/ui/generator/clone-impl-static.stderr +++ b/tests/ui/generator/clone-impl-static.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]: Copy` is not satisfied +error[E0277]: the trait bound `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}: Copy` is not satisfied --> $DIR/clone-impl-static.rs:10:16 | LL | check_copy(&gen); - | ---------- ^^^^ the trait `Copy` is not implemented for `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]` + | ---------- ^^^^ the trait `Copy` is not implemented for `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}` | | | required by a bound introduced by this call | @@ -12,11 +12,11 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]: Clone` is not satisfied +error[E0277]: the trait bound `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}: Clone` is not satisfied --> $DIR/clone-impl-static.rs:12:17 | LL | check_clone(&gen); - | ----------- ^^^^ the trait `Clone` is not implemented for `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]` + | ----------- ^^^^ the trait `Clone` is not implemented for `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}` | | | required by a bound introduced by this call | diff --git a/tests/ui/generator/clone-impl.stderr b/tests/ui/generator/clone-impl.stderr index 64eb47c1a5a03..870216398b1a1 100644 --- a/tests/ui/generator/clone-impl.stderr +++ b/tests/ui/generator/clone-impl.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:36:23: 36:30]` - --> $DIR/clone-impl.rs:42:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:36:23: 36:30}` + --> $DIR/clone-impl.rs:42:5 | LL | let gen_clone_0 = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:36:23: 36:30]` + | ------- within this `{generator@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:36:23: 36:30]`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:40:14 @@ -18,14 +18,14 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:36:23: 36:30]` - --> $DIR/clone-impl.rs:42:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:36:23: 36:30}` + --> $DIR/clone-impl.rs:42:5 | LL | let gen_clone_0 = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:36:23: 36:30]` + | ------- within this `{generator@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:36:23: 36:30]`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` | note: generator does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:38:9 @@ -34,23 +34,20 @@ LL | let v = vec!['a']; | - has type `Vec` which does not implement `Copy` LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later -... -LL | }; - | - `v` is later dropped here note: required by a bound in `check_copy` --> $DIR/clone-impl.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:46:23: 46:30]` - --> $DIR/clone-impl.rs:58:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:46:23: 46:30}` + --> $DIR/clone-impl.rs:58:5 | LL | let gen_clone_1 = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:46:23: 46:30]` + | ------- within this `{generator@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:46:23: 46:30]`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:56:14 @@ -63,14 +60,14 @@ note: required by a bound in `check_copy` LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:46:23: 46:30]` - --> $DIR/clone-impl.rs:58:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:46:23: 46:30}` + --> $DIR/clone-impl.rs:58:5 | LL | let gen_clone_1 = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:46:23: 46:30]` + | ------- within this `{generator@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:46:23: 46:30]`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` | note: generator does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:52:9 @@ -80,23 +77,20 @@ LL | let v = vec!['a']; ... LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later -... -LL | }; - | - `v` is later dropped here note: required by a bound in `check_copy` --> $DIR/clone-impl.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:62:25: 62:32]` - --> $DIR/clone-impl.rs:66:16 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:62:25: 62:32}` + --> $DIR/clone-impl.rs:66:5 | LL | let gen_non_clone = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:62:25: 62:32]` + | ------- within this `{generator@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:62:25: 62:32]`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:64:14 @@ -114,14 +108,14 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `[generator@$DIR/clone-impl.rs:62:25: 62:32]` - --> $DIR/clone-impl.rs:68:17 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{generator@$DIR/clone-impl.rs:62:25: 62:32}` + --> $DIR/clone-impl.rs:68:5 | LL | let gen_non_clone = move || { - | ------- within this `[generator@$DIR/clone-impl.rs:62:25: 62:32]` + | ------- within this `{generator@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:62:25: 62:32]`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone` | note: captured value does not implement `Clone` --> $DIR/clone-impl.rs:64:14 diff --git a/tests/ui/generator/derived-drop-parent-expr.rs b/tests/ui/generator/derived-drop-parent-expr.rs index 4bd34346a1815..e381924517d35 100644 --- a/tests/ui/generator/derived-drop-parent-expr.rs +++ b/tests/ui/generator/derived-drop-parent-expr.rs @@ -1,5 +1,4 @@ // build-pass -// compile-flags:-Zdrop-tracking //! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR #![feature(generators)] diff --git a/tests/ui/generator/drop-control-flow.rs b/tests/ui/generator/drop-control-flow.rs index c6efda9541fb1..1c25c06ba4ccf 100644 --- a/tests/ui/generator/drop-control-flow.rs +++ b/tests/ui/generator/drop-control-flow.rs @@ -1,5 +1,4 @@ // build-pass -// compile-flags: -Zdrop-tracking // A test to ensure generators capture values that were conditionally dropped, // and also that values that are dropped along all paths to a yield do not get diff --git a/tests/ui/generator/drop-track-addassign-yield.rs b/tests/ui/generator/drop-track-addassign-yield.rs index 71cfb170bf6aa..1e64f1d2ec736 100644 --- a/tests/ui/generator/drop-track-addassign-yield.rs +++ b/tests/ui/generator/drop-track-addassign-yield.rs @@ -1,5 +1,4 @@ // run-pass -// compile-flags: -Zdrop-tracking // Based on addassign-yield.rs, but with drop tracking enabled. Originally we did not implement // the fake_read callback on ExprUseVisitor which caused this case to break. diff --git a/tests/ui/generator/drop-tracking-error-body.rs b/tests/ui/generator/drop-tracking-error-body.rs deleted file mode 100644 index f99d9ab6bf860..0000000000000 --- a/tests/ui/generator/drop-tracking-error-body.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags: -Zdrop-tracking-mir --edition=2021 - -#![feature(generators)] - -pub async fn async_bad_body() { - match true {} //~ ERROR non-exhaustive patterns: type `bool` is non-empty -} - -pub fn generator_bad_body() { - || { - // 'non-exhaustive pattern' only seems to be reported once, so this annotation doesn't work - // keep the function around so we can make sure it doesn't ICE - match true {}; // ERROR non-exhaustive patterns: type `bool` is non-empty - yield (); - }; -} - -fn main() {} diff --git a/tests/ui/generator/drop-tracking-error-body.stderr b/tests/ui/generator/drop-tracking-error-body.stderr deleted file mode 100644 index 28a6892336ff2..0000000000000 --- a/tests/ui/generator/drop-tracking-error-body.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0004]: non-exhaustive patterns: type `bool` is non-empty - --> $DIR/drop-tracking-error-body.rs:6:11 - | -LL | match true {} - | ^^^^ - | - = note: the matched value is of type `bool` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match true { -LL + _ => todo!(), -LL ~ } - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr b/tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr deleted file mode 100644 index c07906ec37d30..0000000000000 --- a/tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr +++ /dev/null @@ -1,128 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - diff --git a/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr b/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr deleted file mode 100644 index 1a05bfe4f0e6a..0000000000000 --- a/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr +++ /dev/null @@ -1,334 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `copy::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `copy::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `copy::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `copy::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 8 previous errors - diff --git a/tests/ui/generator/drop-tracking-parent-expression.rs b/tests/ui/generator/drop-tracking-parent-expression.rs index ed9ac6d11adb1..198b14528aad5 100644 --- a/tests/ui/generator/drop-tracking-parent-expression.rs +++ b/tests/ui/generator/drop-tracking-parent-expression.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - #![feature(generators, negative_impls, rustc_attrs)] macro_rules! type_combinations { @@ -21,14 +17,13 @@ macro_rules! type_combinations { let g = move || match drop($name::Client { ..$name::Client::default() }) { //~^ `significant_drop::Client` which is not `Send` //~| `insignificant_dtor::Client` which is not `Send` - //[no_drop_tracking,drop_tracking]~| `derived_drop::Client` which is not `Send` + //~| `derived_drop::Client` which is not `Send` _ => yield, }; assert_send(g); //~^ ERROR cannot be sent between threads //~| ERROR cannot be sent between threads //~| ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads } // Simple owned value. This works because the Client is considered moved into `drop`, @@ -38,10 +33,6 @@ macro_rules! type_combinations { _ => yield, }; assert_send(g); - //[no_drop_tracking]~^ ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads } )* } } diff --git a/tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr b/tests/ui/generator/drop-tracking-parent-expression.stderr similarity index 84% rename from tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr rename to tests/ui/generator/drop-tracking-parent-expression.stderr index 35698a98dbd62..e85bb1347a798 100644 --- a/tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr +++ b/tests/ui/generator/drop-tracking-parent-expression.stderr @@ -1,5 +1,5 @@ error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:13 + --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -13,9 +13,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 + --> $DIR/drop-tracking-parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `derived_drop::Client` which is not `Send` @@ -32,14 +32,14 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 + --> $DIR/drop-tracking-parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:13 + --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -53,9 +53,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 + --> $DIR/drop-tracking-parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `significant_drop::Client` which is not `Send` @@ -72,14 +72,14 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 + --> $DIR/drop-tracking-parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: generator cannot be sent between threads safely - --> $DIR/drop-tracking-parent-expression.rs:27:13 + --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -93,9 +93,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/drop-tracking-parent-expression.rs:25:22 + --> $DIR/drop-tracking-parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `insignificant_dtor::Client` which is not `Send` @@ -112,7 +112,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/drop-tracking-parent-expression.rs:49:19 + --> $DIR/drop-tracking-parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs index cbc291701cbc9..92e0136d51b15 100644 --- a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs +++ b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs @@ -1,8 +1,5 @@ // build-pass // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(generators)] diff --git a/tests/ui/generator/drop-yield-twice.stderr b/tests/ui/generator/drop-yield-twice.stderr index 0808a2c85ee1d..39a906f0bf4c0 100644 --- a/tests/ui/generator/drop-yield-twice.stderr +++ b/tests/ui/generator/drop-yield-twice.stderr @@ -1,16 +1,10 @@ error: generator cannot be sent between threads safely - --> $DIR/drop-yield-twice.rs:7:17 + --> $DIR/drop-yield-twice.rs:7:5 | -LL | assert_send(|| { - | _________________^ -LL | | let guard = Foo(42); -LL | | yield; -LL | | drop(guard); -LL | | yield; -LL | | }) - | |_____^ generator is not `Send` +LL | assert_send(|| { + | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 7:19]`, the trait `Send` is not implemented for `Foo` + = help: within `{generator@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo` note: generator is not `Send` as this value is used across a yield --> $DIR/drop-yield-twice.rs:9:9 | @@ -18,9 +12,6 @@ LL | let guard = Foo(42); | ----- has type `Foo` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `guard` maybe used later -... -LL | }) - | - `guard` is later dropped here note: required by a bound in `assert_send` --> $DIR/drop-yield-twice.rs:15:19 | diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.stderr b/tests/ui/generator/generator-yielding-or-returning-itself.stderr index a26dbf3f27c46..7841a0854ca98 100644 --- a/tests/ui/generator/generator-yielding-or-returning-itself.stderr +++ b/tests/ui/generator/generator-yielding-or-returning-itself.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36]` +error[E0271]: type mismatch resolving `<{generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36} as Generator>::Return == {generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36}` --> $DIR/generator-yielding-or-returning-itself.rs:15:34 | LL | want_cyclic_generator_return(|| { @@ -23,7 +23,7 @@ LL | pub fn want_cyclic_generator_return(_: T) LL | where T: Generator | ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return` -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35]` +error[E0271]: type mismatch resolving `<{generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35} as Generator>::Yield == {generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35}` --> $DIR/generator-yielding-or-returning-itself.rs:28:33 | LL | want_cyclic_generator_yield(|| { diff --git a/tests/ui/generator/issue-102645.rs b/tests/ui/generator/issue-102645.rs index 35acd5cd727c2..677cc69d3f2db 100644 --- a/tests/ui/generator/issue-102645.rs +++ b/tests/ui/generator/issue-102645.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zdrop-tracking - #![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/tests/ui/generator/issue-102645.stderr b/tests/ui/generator/issue-102645.stderr index 3f9a4c2f3c507..5d28dfc45b313 100644 --- a/tests/ui/generator/issue-102645.stderr +++ b/tests/ui/generator/issue-102645.stderr @@ -1,5 +1,5 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied - --> $DIR/issue-102645.rs:16:22 + --> $DIR/issue-102645.rs:14:22 | LL | Pin::new(&mut b).resume(); | ^^^^^^-- an argument of type `()` is missing diff --git a/tests/ui/generator/issue-105084.rs b/tests/ui/generator/issue-105084.rs index ff9357b76a08b..50b5da6e6adfd 100644 --- a/tests/ui/generator/issue-105084.rs +++ b/tests/ui/generator/issue-105084.rs @@ -1,11 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [no_drop_tracking] known-bug: #105084 -// [no_drop_tracking] check-pass -// [drop_tracking] known-bug: #105084 -// [drop_tracking] check-pass - #![feature(generators)] #![feature(generator_clone)] #![feature(generator_trait)] @@ -37,13 +29,13 @@ fn main() { // As it is not taken into account for trait computation, // the generator is `Copy`. let mut h = copy(g); - //[drop_tracking_mir]~^ ERROR the trait bound `Box<(i32, ())>: Copy` is not satisfied in + //~^ ERROR the trait bound `Box<(i32, ())>: Copy` is not satisfied in // We now have 2 boxes with the same backing allocation: // one inside `g` and one inside `h`. // Proceed and drop `t` in `g`. Pin::new(&mut g).resume(()); - //[drop_tracking_mir]~^ ERROR borrow of moved value: `g` + //~^ ERROR borrow of moved value: `g` // Proceed and drop `t` in `h` -> double free! Pin::new(&mut h).resume(()); diff --git a/tests/ui/generator/issue-105084.drop_tracking_mir.stderr b/tests/ui/generator/issue-105084.stderr similarity index 72% rename from tests/ui/generator/issue-105084.drop_tracking_mir.stderr rename to tests/ui/generator/issue-105084.stderr index 1cd4c4e4d6c84..573c31f113402 100644 --- a/tests/ui/generator/issue-105084.drop_tracking_mir.stderr +++ b/tests/ui/generator/issue-105084.stderr @@ -1,8 +1,8 @@ error[E0382]: borrow of moved value: `g` - --> $DIR/issue-105084.rs:45:14 + --> $DIR/issue-105084.rs:37:14 | LL | let mut g = || { - | ----- move occurs because `g` has type `[generator@$DIR/issue-105084.rs:22:17: 22:19]`, which does not implement the `Copy` trait + | ----- move occurs because `g` has type `{generator@$DIR/issue-105084.rs:14:17: 14:19}`, which does not implement the `Copy` trait ... LL | let mut h = copy(g); | - value moved here @@ -11,7 +11,7 @@ LL | Pin::new(&mut g).resume(()); | ^^^^^^ value borrowed here after move | note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary - --> $DIR/issue-105084.rs:17:21 + --> $DIR/issue-105084.rs:9:21 | LL | fn copy(x: T) -> T { | ---- ^ this parameter takes ownership of the value @@ -22,17 +22,17 @@ help: consider cloning the value if the performance cost is acceptable LL | let mut h = copy(g.clone()); | ++++++++ -error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `[generator@$DIR/issue-105084.rs:22:17: 22:19]` - --> $DIR/issue-105084.rs:39:17 +error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{generator@$DIR/issue-105084.rs:14:17: 14:19}` + --> $DIR/issue-105084.rs:31:17 | LL | let mut g = || { - | -- within this `[generator@$DIR/issue-105084.rs:22:17: 22:19]` + | -- within this `{generator@$DIR/issue-105084.rs:14:17: 14:19}` ... LL | let mut h = copy(g); - | ^^^^ within `[generator@$DIR/issue-105084.rs:22:17: 22:19]`, the trait `Copy` is not implemented for `Box<(i32, ())>` + | ^^^^ within `{generator@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>` | note: generator does not implement `Copy` as this value is used across a yield - --> $DIR/issue-105084.rs:29:22 + --> $DIR/issue-105084.rs:21:22 | LL | Box::new((5, yield)); | -------------^^^^^-- @@ -40,7 +40,7 @@ LL | Box::new((5, yield)); | | yield occurs here, with `Box::new((5, yield))` maybe used later | has type `Box<(i32, ())>` which does not implement `Copy` note: required by a bound in `copy` - --> $DIR/issue-105084.rs:17:12 + --> $DIR/issue-105084.rs:9:12 | LL | fn copy(x: T) -> T { | ^^^^ required by this bound in `copy` diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs b/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs index 9408acc15f965..a45479e5300d8 100644 --- a/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs +++ b/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs @@ -1,5 +1,4 @@ // edition:2021 -// compile-flags: -Zdrop-tracking-mir=yes #![feature(generators)] fn main() { diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr b/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr index 4d72ebe79eb49..66f0e3d94bdab 100644 --- a/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr +++ b/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time - --> $DIR/issue-110929-generator-conflict-error-ice.rs:9:9 + --> $DIR/issue-110929-generator-conflict-error-ice.rs:8:9 | LL | let _c = || yield *&mut *x; | -- -- first borrow occurs due to use of `*x` in generator diff --git a/tests/ui/generator/issue-57017.no_drop_tracking.stderr b/tests/ui/generator/issue-57017.no_drop_tracking.stderr deleted file mode 100644 index f7b8e198cc4bf..0000000000000 --- a/tests/ui/generator/issue-57017.no_drop_tracking.stderr +++ /dev/null @@ -1,248 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:32:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: the trait `Sync` is not implemented for `copy::unsync::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:30:28 - | -LL | let g = move || match drop(&$name::unsync::Client::default()) { - | --------------------------------- has type `©::unsync::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later -LL | }; - | - `&$name::unsync::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:44:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `copy::unsend::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:42:28 - | -LL | let g = move || match drop($name::unsend::Client::default()) { - | -------------------------------- has type `copy::unsend::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later -LL | }; - | - `$name::unsend::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:32:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: the trait `Sync` is not implemented for `derived_drop::unsync::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:30:28 - | -LL | let g = move || match drop(&$name::unsync::Client::default()) { - | --------------------------------- has type `&derived_drop::unsync::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later -LL | }; - | - `&$name::unsync::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:44:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `derived_drop::unsend::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:42:28 - | -LL | let g = move || match drop($name::unsend::Client::default()) { - | -------------------------------- has type `derived_drop::unsend::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later -LL | }; - | - `$name::unsend::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:32:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: the trait `Sync` is not implemented for `significant_drop::unsync::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:30:28 - | -LL | let g = move || match drop(&$name::unsync::Client::default()) { - | --------------------------------- has type `&significant_drop::unsync::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later -LL | }; - | - `&$name::unsync::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/issue-57017.rs:44:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `significant_drop::unsend::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57017.rs:42:28 - | -LL | let g = move || match drop($name::unsend::Client::default()) { - | -------------------------------- has type `significant_drop::unsend::Client` which is not `Send` -LL | _status => yield, - | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later -LL | }; - | - `$name::unsend::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; -LL | | significant_drop => { -... | -LL | | } -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/issue-57017.rs:52:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 6 previous errors - diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs index 381897c77a5c3..bb2d6679b6763 100644 --- a/tests/ui/generator/issue-57017.rs +++ b/tests/ui/generator/issue-57017.rs @@ -1,9 +1,4 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [drop_tracking] build-pass -// [drop_tracking_mir] build-pass - +// build-pass #![feature(generators, negative_impls)] #![allow(dropping_references, dropping_copy_types)] @@ -30,9 +25,6 @@ macro_rules! type_combinations { _status => yield, }; assert_send(g); - //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely - //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely - //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely } // This tests that `Client` is properly considered to be dropped after moving it into the @@ -42,9 +34,6 @@ macro_rules! type_combinations { _status => yield, }; assert_send(g); - //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely - //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely - //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely } )* } } diff --git a/tests/ui/generator/issue-57478.no_drop_tracking.stderr b/tests/ui/generator/issue-57478.no_drop_tracking.stderr deleted file mode 100644 index 612dd9c37f701..0000000000000 --- a/tests/ui/generator/issue-57478.no_drop_tracking.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/issue-57478.rs:13:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let guard = Foo; -LL | | drop(guard); -LL | | yield; -LL | | }) - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/issue-57478.rs:13:17: 13:19]`, the trait `Send` is not implemented for `Foo` -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-57478.rs:17:9 - | -LL | let guard = Foo; - | ----- has type `Foo` which is not `Send` -LL | drop(guard); -LL | yield; - | ^^^^^ yield occurs here, with `guard` maybe used later -LL | }) - | - `guard` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/issue-57478.rs:21:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to previous error - diff --git a/tests/ui/generator/issue-57478.rs b/tests/ui/generator/issue-57478.rs index 3c23b5992710e..39710febdb95c 100644 --- a/tests/ui/generator/issue-57478.rs +++ b/tests/ui/generator/issue-57478.rs @@ -1,8 +1,4 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [drop_tracking] check-pass -// [drop_tracking_mir] check-pass +// check-pass #![feature(negative_impls, generators)] @@ -11,7 +7,6 @@ impl !Send for Foo {} fn main() { assert_send(|| { - //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely let guard = Foo; drop(guard); yield; diff --git a/tests/ui/generator/issue-68112.drop_tracking.stderr b/tests/ui/generator/issue-68112.drop_tracking.stderr deleted file mode 100644 index 282eac1b686ef..0000000000000 --- a/tests/ui/generator/issue-68112.drop_tracking.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/issue-68112.rs:43:18 - | -LL | require_send(send_gen); - | ^^^^^^^^ generator is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-68112.rs:39:9 - | -LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `impl Generator>>` which is not `Send` -LL | -LL | yield; - | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later -... -LL | }; - | - `_non_send_gen` is later dropped here -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:67:18 - | -LL | require_send(send_gen); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this generator - --> $DIR/issue-68112.rs:52:5 - | -LL | || { - | ^^ -note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:49:30 - | -LL | pub fn make_gen2(t: T) -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:57:34 - | -LL | fn make_non_send_generator2() -> impl Generator>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `impl Generator>>`, `()` -note: required because it's used within this generator - --> $DIR/issue-68112.rs:63:20 - | -LL | let send_gen = || { - | ^^ -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/issue-68112.no_drop_tracking.stderr b/tests/ui/generator/issue-68112.no_drop_tracking.stderr deleted file mode 100644 index 282eac1b686ef..0000000000000 --- a/tests/ui/generator/issue-68112.no_drop_tracking.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/issue-68112.rs:43:18 - | -LL | require_send(send_gen); - | ^^^^^^^^ generator is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-68112.rs:39:9 - | -LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `impl Generator>>` which is not `Send` -LL | -LL | yield; - | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later -... -LL | }; - | - `_non_send_gen` is later dropped here -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:67:18 - | -LL | require_send(send_gen); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this generator - --> $DIR/issue-68112.rs:52:5 - | -LL | || { - | ^^ -note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:49:30 - | -LL | pub fn make_gen2(t: T) -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:57:34 - | -LL | fn make_non_send_generator2() -> impl Generator>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `impl Generator>>`, `()` -note: required because it's used within this generator - --> $DIR/issue-68112.rs:63:20 - | -LL | let send_gen = || { - | ^^ -note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/issue-68112.rs b/tests/ui/generator/issue-68112.rs index 48b53b7693d41..9dd68726f9288 100644 --- a/tests/ui/generator/issue-68112.rs +++ b/tests/ui/generator/issue-68112.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(generators, generator_trait)] use std::{ @@ -39,7 +36,7 @@ fn test1() { yield; //~^ NOTE yield occurs here //~| NOTE value is used across a yield - }; //[no_drop_tracking,drop_tracking]~ NOTE later dropped here + }; require_send(send_gen); //~^ ERROR generator cannot be sent between threads //~| NOTE not `Send` @@ -68,7 +65,6 @@ fn test2() { //~^ ERROR `RefCell` cannot be shared between threads safely //~| NOTE `RefCell` cannot be shared between threads safely //~| NOTE required for - //[no_drop_tracking,drop_tracking]~| NOTE required by a bound introduced by this call //~| NOTE captures the following types //~| NOTE use `std::sync::RwLock` instead } diff --git a/tests/ui/generator/issue-68112.drop_tracking_mir.stderr b/tests/ui/generator/issue-68112.stderr similarity index 89% rename from tests/ui/generator/issue-68112.drop_tracking_mir.stderr rename to tests/ui/generator/issue-68112.stderr index a83522b714d53..8080048222ffb 100644 --- a/tests/ui/generator/issue-68112.drop_tracking_mir.stderr +++ b/tests/ui/generator/issue-68112.stderr @@ -1,5 +1,5 @@ error: generator cannot be sent between threads safely - --> $DIR/issue-68112.rs:43:5 + --> $DIR/issue-68112.rs:40:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ generator is not `Send` @@ -7,7 +7,7 @@ LL | require_send(send_gen); = help: the trait `Sync` is not implemented for `RefCell` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-68112.rs:39:9 + --> $DIR/issue-68112.rs:36:9 | LL | let _non_send_gen = make_non_send_generator(); | ------------- has type `impl Generator>>` which is not `Send` @@ -15,13 +15,13 @@ LL | LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 + --> $DIR/issue-68112.rs:22:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:67:5 + --> $DIR/issue-68112.rs:64:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely @@ -30,28 +30,28 @@ LL | require_send(send_gen); = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this generator - --> $DIR/issue-68112.rs:52:5 + --> $DIR/issue-68112.rs:49:5 | LL | || { | ^^ note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:49:30 + --> $DIR/issue-68112.rs:46:30 | LL | pub fn make_gen2(t: T) -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it appears within the type `impl Generator>>` - --> $DIR/issue-68112.rs:57:34 + --> $DIR/issue-68112.rs:54:34 | LL | fn make_non_send_generator2() -> impl Generator>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: required because it captures the following types: `impl Generator>>` note: required because it's used within this generator - --> $DIR/issue-68112.rs:63:20 + --> $DIR/issue-68112.rs:60:20 | LL | let send_gen = || { | ^^ note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:25:25 + --> $DIR/issue-68112.rs:22:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` diff --git a/tests/ui/generator/issue-93161.rs b/tests/ui/generator/issue-93161.rs index 8d3f7c62f3936..ae8603b7c09fa 100644 --- a/tests/ui/generator/issue-93161.rs +++ b/tests/ui/generator/issue-93161.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2021 // run-pass diff --git a/tests/ui/generator/not-send-sync.drop_tracking.stderr b/tests/ui/generator/not-send-sync.drop_tracking.stderr deleted file mode 100644 index 718fd42245ad3..0000000000000 --- a/tests/ui/generator/not-send-sync.drop_tracking.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: generator cannot be shared between threads safely - --> $DIR/not-send-sync.rs:17:17 - | -LL | assert_sync(|| { - | _________________^ -LL | | -LL | | let a = NotSync; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Sync` - | - = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync` -note: generator is not `Sync` as this value is used across a yield - --> $DIR/not-send-sync.rs:20:9 - | -LL | let a = NotSync; - | - has type `NotSync` which is not `Sync` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_sync` - --> $DIR/not-send-sync.rs:14:23 - | -LL | fn assert_sync(_: T) {} - | ^^^^ required by this bound in `assert_sync` - -error: generator cannot be sent between threads safely - --> $DIR/not-send-sync.rs:24:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let a = NotSend; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend` -note: generator is not `Send` as this value is used across a yield - --> $DIR/not-send-sync.rs:27:9 - | -LL | let a = NotSend; - | - has type `NotSend` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/not-send-sync.rs:15:23 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/not-send-sync.no_drop_tracking.stderr b/tests/ui/generator/not-send-sync.no_drop_tracking.stderr deleted file mode 100644 index 718fd42245ad3..0000000000000 --- a/tests/ui/generator/not-send-sync.no_drop_tracking.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: generator cannot be shared between threads safely - --> $DIR/not-send-sync.rs:17:17 - | -LL | assert_sync(|| { - | _________________^ -LL | | -LL | | let a = NotSync; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Sync` - | - = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync` -note: generator is not `Sync` as this value is used across a yield - --> $DIR/not-send-sync.rs:20:9 - | -LL | let a = NotSync; - | - has type `NotSync` which is not `Sync` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_sync` - --> $DIR/not-send-sync.rs:14:23 - | -LL | fn assert_sync(_: T) {} - | ^^^^ required by this bound in `assert_sync` - -error: generator cannot be sent between threads safely - --> $DIR/not-send-sync.rs:24:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let a = NotSend; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend` -note: generator is not `Send` as this value is used across a yield - --> $DIR/not-send-sync.rs:27:9 - | -LL | let a = NotSend; - | - has type `NotSend` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/not-send-sync.rs:15:23 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/not-send-sync.rs b/tests/ui/generator/not-send-sync.rs index 8794db452b465..16c8cd476291c 100644 --- a/tests/ui/generator/not-send-sync.rs +++ b/tests/ui/generator/not-send-sync.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(generators)] #![feature(negative_impls)] diff --git a/tests/ui/generator/not-send-sync.drop_tracking_mir.stderr b/tests/ui/generator/not-send-sync.stderr similarity index 72% rename from tests/ui/generator/not-send-sync.drop_tracking_mir.stderr rename to tests/ui/generator/not-send-sync.stderr index 66f01ae37d81a..13ce687e0bb45 100644 --- a/tests/ui/generator/not-send-sync.drop_tracking_mir.stderr +++ b/tests/ui/generator/not-send-sync.stderr @@ -1,39 +1,39 @@ error: generator cannot be shared between threads safely - --> $DIR/not-send-sync.rs:17:5 + --> $DIR/not-send-sync.rs:14:5 | LL | assert_sync(|| { | ^^^^^^^^^^^ generator is not `Sync` | - = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync` + = help: within `{generator@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync` note: generator is not `Sync` as this value is used across a yield - --> $DIR/not-send-sync.rs:20:9 + --> $DIR/not-send-sync.rs:17:9 | LL | let a = NotSync; | - has type `NotSync` which is not `Sync` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later note: required by a bound in `assert_sync` - --> $DIR/not-send-sync.rs:14:23 + --> $DIR/not-send-sync.rs:11:23 | LL | fn assert_sync(_: T) {} | ^^^^ required by this bound in `assert_sync` error: generator cannot be sent between threads safely - --> $DIR/not-send-sync.rs:24:5 + --> $DIR/not-send-sync.rs:21:5 | LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend` + = help: within `{generator@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend` note: generator is not `Send` as this value is used across a yield - --> $DIR/not-send-sync.rs:27:9 + --> $DIR/not-send-sync.rs:24:9 | LL | let a = NotSend; | - has type `NotSend` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later note: required by a bound in `assert_send` - --> $DIR/not-send-sync.rs:15:23 + --> $DIR/not-send-sync.rs:12:23 | LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/generator/parent-expression.drop_tracking.stderr b/tests/ui/generator/parent-expression.drop_tracking.stderr deleted file mode 100644 index ef489088bf853..0000000000000 --- a/tests/ui/generator/parent-expression.drop_tracking.stderr +++ /dev/null @@ -1,128 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - diff --git a/tests/ui/generator/parent-expression.no_drop_tracking.stderr b/tests/ui/generator/parent-expression.no_drop_tracking.stderr deleted file mode 100644 index 2e1313a800487..0000000000000 --- a/tests/ui/generator/parent-expression.no_drop_tracking.stderr +++ /dev/null @@ -1,334 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `copy::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `copy::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `copy::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `copy::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `derived_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `derived_drop::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `significant_drop::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `significant_drop::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 - | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -... -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:40:25 - | -LL | assert_send(g); - | ^ generator is not `Send` -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation - | - = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` -note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:38:22 - | -LL | let g = move || match drop($name::Client::default()) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` -LL | _ => yield, - | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later -LL | }; - | - `$name::Client::default()` is later dropped here -... -LL | / type_combinations!( -LL | | // OK -LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though -... | -LL | | }; -LL | | ); - | |_____- in this macro invocation -note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 - | -LL | fn assert_send(_thing: T) {} - | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 8 previous errors - diff --git a/tests/ui/generator/parent-expression.rs b/tests/ui/generator/parent-expression.rs index 239034e3d4e8a..198b14528aad5 100644 --- a/tests/ui/generator/parent-expression.rs +++ b/tests/ui/generator/parent-expression.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - #![feature(generators, negative_impls, rustc_attrs)] macro_rules! type_combinations { @@ -28,7 +24,6 @@ macro_rules! type_combinations { //~^ ERROR cannot be sent between threads //~| ERROR cannot be sent between threads //~| ERROR cannot be sent between threads - //[no_drop_tracking]~^^^^ ERROR cannot be sent between threads } // Simple owned value. This works because the Client is considered moved into `drop`, @@ -38,10 +33,6 @@ macro_rules! type_combinations { _ => yield, }; assert_send(g); - //[no_drop_tracking]~^ ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads - //[no_drop_tracking]~| ERROR cannot be sent between threads } )* } } diff --git a/tests/ui/generator/parent-expression.drop_tracking_mir.stderr b/tests/ui/generator/parent-expression.stderr similarity index 86% rename from tests/ui/generator/parent-expression.drop_tracking_mir.stderr rename to tests/ui/generator/parent-expression.stderr index bf814456427e0..25a3b051b1f0a 100644 --- a/tests/ui/generator/parent-expression.drop_tracking_mir.stderr +++ b/tests/ui/generator/parent-expression.stderr @@ -1,5 +1,5 @@ error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:13 + --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -13,9 +13,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 + --> $DIR/parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `derived_drop::Client` which is not `Send` @@ -32,14 +32,14 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 + --> $DIR/parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:13 + --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -53,9 +53,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 + --> $DIR/parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `significant_drop::Client` which is not `Send` @@ -72,14 +72,14 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 + --> $DIR/parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: generator cannot be sent between threads safely - --> $DIR/parent-expression.rs:27:13 + --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); | ^^^^^^^^^^^ generator is not `Send` @@ -93,9 +93,9 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` note: generator is not `Send` as this value is used across a yield - --> $DIR/parent-expression.rs:25:22 + --> $DIR/parent-expression.rs:21:22 | LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { | ------------------------ has type `insignificant_dtor::Client` which is not `Send` @@ -112,7 +112,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation note: required by a bound in `assert_send` - --> $DIR/parent-expression.rs:49:19 + --> $DIR/parent-expression.rs:40:19 | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/generator/partial-drop.drop_tracking.stderr b/tests/ui/generator/partial-drop.drop_tracking.stderr deleted file mode 100644 index f1b25cb8c34e9..0000000000000 --- a/tests/ui/generator/partial-drop.drop_tracking.stderr +++ /dev/null @@ -1,61 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/partial-drop.rs:17:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let guard = Bar { foo: Foo, x: 42 }; -LL | | drop(guard.foo); -LL | | yield; -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/partial-drop.rs:17:17: 17:19]`, the trait `Send` is not implemented for `Foo` -note: generator is not `Send` as this value is used across a yield - --> $DIR/partial-drop.rs:21:9 - | -LL | let guard = Bar { foo: Foo, x: 42 }; - | ----- has type `Bar` which is not `Send` -LL | drop(guard.foo); -LL | yield; - | ^^^^^ yield occurs here, with `guard` maybe used later -LL | }); - | - `guard` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/partial-drop.rs:33:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: generator cannot be sent between threads safely - --> $DIR/partial-drop.rs:24:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let guard = Bar { foo: Foo, x: 42 }; -LL | | let Bar { foo, x } = guard; -LL | | drop(foo); -LL | | yield; -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/partial-drop.rs:24:17: 24:19]`, the trait `Send` is not implemented for `Foo` -note: generator is not `Send` as this value is used across a yield - --> $DIR/partial-drop.rs:29:9 - | -LL | let guard = Bar { foo: Foo, x: 42 }; - | ----- has type `Bar` which is not `Send` -... -LL | yield; - | ^^^^^ yield occurs here, with `guard` maybe used later -LL | }); - | - `guard` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/partial-drop.rs:33:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/partial-drop.no_drop_tracking.stderr b/tests/ui/generator/partial-drop.no_drop_tracking.stderr deleted file mode 100644 index 91152b5ea6f3d..0000000000000 --- a/tests/ui/generator/partial-drop.no_drop_tracking.stderr +++ /dev/null @@ -1,61 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/partial-drop.rs:17:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let guard = Bar { foo: Foo, x: 42 }; -LL | | drop(guard.foo); -LL | | yield; -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/partial-drop.rs:17:17: 17:19]`, the trait `Send` is not implemented for `Foo` -note: generator is not `Send` as this value is used across a yield - --> $DIR/partial-drop.rs:21:9 - | -LL | let guard = Bar { foo: Foo, x: 42 }; - | ----- has type `Bar` which is not `Send` -LL | drop(guard.foo); -LL | yield; - | ^^^^^ yield occurs here, with `guard` maybe used later -LL | }); - | - `guard` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/partial-drop.rs:33:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: generator cannot be sent between threads safely - --> $DIR/partial-drop.rs:24:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let guard = Bar { foo: Foo, x: 42 }; -LL | | let Bar { foo, x } = guard; -LL | | drop(foo); -LL | | yield; -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[generator@$DIR/partial-drop.rs:24:17: 24:19]`, the trait `Send` is not implemented for `Foo` -note: generator is not `Send` as this value is used across a yield - --> $DIR/partial-drop.rs:29:9 - | -LL | let Bar { foo, x } = guard; - | --- has type `Foo` which is not `Send` -LL | drop(foo); -LL | yield; - | ^^^^^ yield occurs here, with `foo` maybe used later -LL | }); - | - `foo` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/partial-drop.rs:33:19 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/partial-drop.rs b/tests/ui/generator/partial-drop.rs index 1d3ae075d43af..868f36adce2c2 100644 --- a/tests/ui/generator/partial-drop.rs +++ b/tests/ui/generator/partial-drop.rs @@ -1,8 +1,4 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir -// [drop_tracking_mir] check-pass - +// check-pass #![feature(negative_impls, generators)] struct Foo; @@ -15,14 +11,19 @@ struct Bar { fn main() { assert_send(|| { - //[no_drop_tracking,drop_tracking]~^ ERROR generator cannot be sent between threads safely let guard = Bar { foo: Foo, x: 42 }; drop(guard.foo); yield; }); assert_send(|| { - //[no_drop_tracking,drop_tracking]~^ ERROR generator cannot be sent between threads safely + let mut guard = Bar { foo: Foo, x: 42 }; + drop(guard); + guard = Bar { foo: Foo, x: 23 }; + yield; + }); + + assert_send(|| { let guard = Bar { foo: Foo, x: 42 }; let Bar { foo, x } = guard; drop(foo); diff --git a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr deleted file mode 100644 index 429b202f60383..0000000000000 --- a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr +++ /dev/null @@ -1,64 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-1.rs:40:18 - | -LL | require_send(send_gen); - | ^^^^^^^^ generator is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-1.rs:38:9 - | -LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later -LL | }; - | - `_non_send_gen` is later dropped here -note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/generator-print-verbose-1.rs:59:18 - | -LL | require_send(send_gen); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:45:5 - | -LL | || { - | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` - --> $DIR/generator-print-verbose-1.rs:44:30 - | -LL | pub fn make_gen2(t: T) -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` - --> $DIR/generator-print-verbose-1.rs:50:34 - | -LL | fn make_non_send_generator2() -> impl Generator>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`, `()` -note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:55:20 - | -LL | let send_gen = || { - | ^^ -note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr deleted file mode 100644 index 429b202f60383..0000000000000 --- a/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr +++ /dev/null @@ -1,64 +0,0 @@ -error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-1.rs:40:18 - | -LL | require_send(send_gen); - | ^^^^^^^^ generator is not `Send` - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead -note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-1.rs:38:9 - | -LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later -LL | }; - | - `_non_send_gen` is later dropped here -note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/generator-print-verbose-1.rs:59:18 - | -LL | require_send(send_gen); - | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `RefCell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead - = note: required for `Arc>` to implement `Send` -note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:45:5 - | -LL | || { - | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` - --> $DIR/generator-print-verbose-1.rs:44:30 - | -LL | pub fn make_gen2(t: T) -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` - --> $DIR/generator-print-verbose-1.rs:50:34 - | -LL | fn make_non_send_generator2() -> impl Generator>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`, `()` -note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:55:20 - | -LL | let send_gen = || { - | ^^ -note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 - | -LL | fn require_send(_: impl Send) {} - | ^^^^ required by this bound in `require_send` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/print/generator-print-verbose-1.rs b/tests/ui/generator/print/generator-print-verbose-1.rs index c7052c7d1b04d..e52234c08a352 100644 --- a/tests/ui/generator/print/generator-print-verbose-1.rs +++ b/tests/ui/generator/print/generator-print-verbose-1.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // compile-flags: -Zverbose // Same as: tests/ui/generator/issue-68112.stderr diff --git a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr b/tests/ui/generator/print/generator-print-verbose-1.stderr similarity index 86% rename from tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr rename to tests/ui/generator/print/generator-print-verbose-1.stderr index 01a30fd2f4e99..d949543de41bc 100644 --- a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr +++ b/tests/ui/generator/print/generator-print-verbose-1.stderr @@ -1,5 +1,5 @@ error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-1.rs:40:5 + --> $DIR/generator-print-verbose-1.rs:37:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ generator is not `Send` @@ -7,20 +7,20 @@ LL | require_send(send_gen); = help: the trait `Sync` is not implemented for `RefCell` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-1.rs:38:9 + --> $DIR/generator-print-verbose-1.rs:35:9 | LL | let _non_send_gen = make_non_send_generator(); | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 + --> $DIR/generator-print-verbose-1.rs:26:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/generator-print-verbose-1.rs:59:5 + --> $DIR/generator-print-verbose-1.rs:56:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely @@ -29,28 +29,28 @@ LL | require_send(send_gen); = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:45:5 + --> $DIR/generator-print-verbose-1.rs:42:5 | LL | || { | ^^ note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` - --> $DIR/generator-print-verbose-1.rs:44:30 + --> $DIR/generator-print-verbose-1.rs:41:30 | LL | pub fn make_gen2(t: T) -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` - --> $DIR/generator-print-verbose-1.rs:50:34 + --> $DIR/generator-print-verbose-1.rs:47:34 | LL | fn make_non_send_generator2() -> impl Generator>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` note: required because it's used within this generator - --> $DIR/generator-print-verbose-1.rs:55:20 + --> $DIR/generator-print-verbose-1.rs:52:20 | LL | let send_gen = || { | ^^ note: required by a bound in `require_send` - --> $DIR/generator-print-verbose-1.rs:29:25 + --> $DIR/generator-print-verbose-1.rs:26:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` diff --git a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr deleted file mode 100644 index 1f2e530f6f577..0000000000000 --- a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: generator cannot be shared between threads safely - --> $DIR/generator-print-verbose-2.rs:20:17 - | -LL | assert_sync(|| { - | _________________^ -LL | | -LL | | let a = NotSync; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Sync` - | - = help: within `[main::{closure#0} upvar_tys=() {NotSync, ()}]`, the trait `Sync` is not implemented for `NotSync` -note: generator is not `Sync` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:23:9 - | -LL | let a = NotSync; - | - has type `NotSync` which is not `Sync` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_sync` - --> $DIR/generator-print-verbose-2.rs:17:23 - | -LL | fn assert_sync(_: T) {} - | ^^^^ required by this bound in `assert_sync` - -error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-2.rs:27:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let a = NotSend; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[main::{closure#1} upvar_tys=() {NotSend, ()}]`, the trait `Send` is not implemented for `NotSend` -note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:30:9 - | -LL | let a = NotSend; - | - has type `NotSend` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/generator-print-verbose-2.rs:18:23 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr deleted file mode 100644 index 1f2e530f6f577..0000000000000 --- a/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: generator cannot be shared between threads safely - --> $DIR/generator-print-verbose-2.rs:20:17 - | -LL | assert_sync(|| { - | _________________^ -LL | | -LL | | let a = NotSync; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Sync` - | - = help: within `[main::{closure#0} upvar_tys=() {NotSync, ()}]`, the trait `Sync` is not implemented for `NotSync` -note: generator is not `Sync` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:23:9 - | -LL | let a = NotSync; - | - has type `NotSync` which is not `Sync` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_sync` - --> $DIR/generator-print-verbose-2.rs:17:23 - | -LL | fn assert_sync(_: T) {} - | ^^^^ required by this bound in `assert_sync` - -error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-2.rs:27:17 - | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | let a = NotSend; -LL | | yield; -LL | | drop(a); -LL | | }); - | |_____^ generator is not `Send` - | - = help: within `[main::{closure#1} upvar_tys=() {NotSend, ()}]`, the trait `Send` is not implemented for `NotSend` -note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:30:9 - | -LL | let a = NotSend; - | - has type `NotSend` which is not `Send` -LL | yield; - | ^^^^^ yield occurs here, with `a` maybe used later -LL | drop(a); -LL | }); - | - `a` is later dropped here -note: required by a bound in `assert_send` - --> $DIR/generator-print-verbose-2.rs:18:23 - | -LL | fn assert_send(_: T) {} - | ^^^^ required by this bound in `assert_send` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generator/print/generator-print-verbose-2.rs b/tests/ui/generator/print/generator-print-verbose-2.rs index ab29db6e09c96..e53a7ef8cc137 100644 --- a/tests/ui/generator/print/generator-print-verbose-2.rs +++ b/tests/ui/generator/print/generator-print-verbose-2.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // compile-flags: -Zverbose // Same as test/ui/generator/not-send-sync.rs diff --git a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr b/tests/ui/generator/print/generator-print-verbose-2.stderr similarity index 68% rename from tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr rename to tests/ui/generator/print/generator-print-verbose-2.stderr index 354369f195402..8ff7557619fee 100644 --- a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr +++ b/tests/ui/generator/print/generator-print-verbose-2.stderr @@ -1,39 +1,39 @@ error: generator cannot be shared between threads safely - --> $DIR/generator-print-verbose-2.rs:20:5 + --> $DIR/generator-print-verbose-2.rs:17:5 | LL | assert_sync(|| { | ^^^^^^^^^^^ generator is not `Sync` | - = help: within `[main::{closure#0} upvar_tys=() [main::{closure#0}]]`, the trait `Sync` is not implemented for `NotSync` + = help: within `{main::{closure#0} upvar_tys=() {main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` note: generator is not `Sync` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:23:9 + --> $DIR/generator-print-verbose-2.rs:20:9 | LL | let a = NotSync; | - has type `NotSync` which is not `Sync` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later note: required by a bound in `assert_sync` - --> $DIR/generator-print-verbose-2.rs:17:23 + --> $DIR/generator-print-verbose-2.rs:14:23 | LL | fn assert_sync(_: T) {} | ^^^^ required by this bound in `assert_sync` error: generator cannot be sent between threads safely - --> $DIR/generator-print-verbose-2.rs:27:5 + --> $DIR/generator-print-verbose-2.rs:24:5 | LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[main::{closure#1} upvar_tys=() [main::{closure#1}]]`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() {main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` note: generator is not `Send` as this value is used across a yield - --> $DIR/generator-print-verbose-2.rs:30:9 + --> $DIR/generator-print-verbose-2.rs:27:9 | LL | let a = NotSend; | - has type `NotSend` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later note: required by a bound in `assert_send` - --> $DIR/generator-print-verbose-2.rs:18:23 + --> $DIR/generator-print-verbose-2.rs:15:23 | LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/tests/ui/generator/print/generator-print-verbose-3.stderr b/tests/ui/generator/print/generator-print-verbose-3.stderr index d15646259b2c9..69358ed0a9182 100644 --- a/tests/ui/generator/print/generator-print-verbose-3.stderr +++ b/tests/ui/generator/print/generator-print-verbose-3.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____^ expected `()`, found generator | = note: expected unit type `()` - found generator `[main::{closure#0} upvar_tys=(unavailable)]` + found generator `{main::{closure#0} upvar_tys=(unavailable)}` error: aborting due to previous error diff --git a/tests/ui/generator/ref-upvar-not-send.stderr b/tests/ui/generator/ref-upvar-not-send.stderr index 689ace67e34ef..d6a2be977e4c3 100644 --- a/tests/ui/generator/ref-upvar-not-send.stderr +++ b/tests/ui/generator/ref-upvar-not-send.stderr @@ -34,7 +34,7 @@ LL | | let _y = y; LL | | }); | |_____^ generator is not `Send` | - = help: within `[generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24]`, the trait `Send` is not implemented for `*mut ()` + = help: within `{generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` --> $DIR/ref-upvar-not-send.rs:27:18 | diff --git a/tests/ui/generator/retain-resume-ref.drop_tracking.stderr b/tests/ui/generator/retain-resume-ref.drop_tracking.stderr deleted file mode 100644 index 7122a951e8070..0000000000000 --- a/tests/ui/generator/retain-resume-ref.drop_tracking.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0499]: cannot borrow `thing` as mutable more than once at a time - --> $DIR/retain-resume-ref.rs:27:25 - | -LL | gen.as_mut().resume(&mut thing); - | ---------- first mutable borrow occurs here -LL | gen.as_mut().resume(&mut thing); - | ------ ^^^^^^^^^^ second mutable borrow occurs here - | | - | first borrow later used by call - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr b/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr deleted file mode 100644 index 7122a951e8070..0000000000000 --- a/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0499]: cannot borrow `thing` as mutable more than once at a time - --> $DIR/retain-resume-ref.rs:27:25 - | -LL | gen.as_mut().resume(&mut thing); - | ---------- first mutable borrow occurs here -LL | gen.as_mut().resume(&mut thing); - | ------ ^^^^^^^^^^ second mutable borrow occurs here - | | - | first borrow later used by call - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/generator/retain-resume-ref.rs b/tests/ui/generator/retain-resume-ref.rs index 0050d98d03ba6..0606ea71cdf37 100644 --- a/tests/ui/generator/retain-resume-ref.rs +++ b/tests/ui/generator/retain-resume-ref.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - //! This test ensures that a mutable reference cannot be passed as a resume argument twice. #![feature(generators, generator_trait)] diff --git a/tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr b/tests/ui/generator/retain-resume-ref.stderr similarity index 93% rename from tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr rename to tests/ui/generator/retain-resume-ref.stderr index 736ed1fb60803..bc715c7030eb3 100644 --- a/tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr +++ b/tests/ui/generator/retain-resume-ref.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `thing` as mutable more than once at a time - --> $DIR/retain-resume-ref.rs:27:25 + --> $DIR/retain-resume-ref.rs:23:25 | LL | gen.as_mut().resume(&mut thing); | ---------- first mutable borrow occurs here diff --git a/tests/ui/generator/static-mut-reference-across-yield.rs b/tests/ui/generator/static-mut-reference-across-yield.rs index 4784ff49be2e9..0fa6d9cdc77b6 100644 --- a/tests/ui/generator/static-mut-reference-across-yield.rs +++ b/tests/ui/generator/static-mut-reference-across-yield.rs @@ -1,8 +1,6 @@ // build-pass -// revisions: mir thir drop_tracking drop_tracking_mir +// revisions: mir thir // [thir]compile-flags: -Zthir-unsafeck -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir #![feature(generators)] diff --git a/tests/ui/generator/static-not-unpin.current.stderr b/tests/ui/generator/static-not-unpin.current.stderr index ecd8ca60c6f2c..242489841e802 100644 --- a/tests/ui/generator/static-not-unpin.current.stderr +++ b/tests/ui/generator/static-not-unpin.current.stderr @@ -1,8 +1,8 @@ -error[E0277]: `[static generator@$DIR/static-not-unpin.rs:14:25: 14:34]` cannot be unpinned +error[E0277]: `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned --> $DIR/static-not-unpin.rs:17:18 | LL | assert_unpin(generator); - | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:14:25: 14:34]` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` | | | required by a bound introduced by this call | diff --git a/tests/ui/generator/static-not-unpin.next.stderr b/tests/ui/generator/static-not-unpin.next.stderr index ecd8ca60c6f2c..242489841e802 100644 --- a/tests/ui/generator/static-not-unpin.next.stderr +++ b/tests/ui/generator/static-not-unpin.next.stderr @@ -1,8 +1,8 @@ -error[E0277]: `[static generator@$DIR/static-not-unpin.rs:14:25: 14:34]` cannot be unpinned +error[E0277]: `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned --> $DIR/static-not-unpin.rs:17:18 | LL | assert_unpin(generator); - | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:14:25: 14:34]` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` | | | required by a bound introduced by this call | diff --git a/tests/ui/generator/type-mismatch-signature-deduction.stderr b/tests/ui/generator/type-mismatch-signature-deduction.stderr index ef6d896f8afa3..fe1bade5577c8 100644 --- a/tests/ui/generator/type-mismatch-signature-deduction.stderr +++ b/tests/ui/generator/type-mismatch-signature-deduction.stderr @@ -18,7 +18,7 @@ LL | Ok(5) LL | Err(5) | ++++ + -error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7] as Generator>::Return == i32` +error[E0271]: type mismatch resolving `<{generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7} as Generator>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Generator { diff --git a/tests/ui/generator/unresolved-ct-var-drop-tracking.rs b/tests/ui/generator/unresolved-ct-var-drop-tracking.rs deleted file mode 100644 index a6589348d301e..0000000000000 --- a/tests/ui/generator/unresolved-ct-var-drop-tracking.rs +++ /dev/null @@ -1,15 +0,0 @@ -// incremental -// edition:2021 -// compile-flags: -Zdrop-tracking - -fn main() { - let _ = async { - let s = std::array::from_fn(|_| ()).await; - //~^ ERROR `[(); _]` is not a future - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - }; -} diff --git a/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr b/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr deleted file mode 100644 index dec0141ab6717..0000000000000 --- a/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr +++ /dev/null @@ -1,78 +0,0 @@ -error[E0277]: `[(); _]` is not a future - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ----------------------------^^^^^ - | | || - | | |`[(); _]` is not a future - | | help: remove the `.await` - | this call returns `[(); _]` - | - = help: the trait `Future` is not implemented for `[(); _]` - = note: [(); _] must be a future or must implement `IntoFuture` to be awaited - = note: required for `[(); _]` to implement `IntoFuture` - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var-drop-tracking.rs:7:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0277, E0698. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/unresolved-ct-var.rs b/tests/ui/generator/unresolved-ct-var.rs index 0a1570fc2395e..0316385fba93a 100644 --- a/tests/ui/generator/unresolved-ct-var.rs +++ b/tests/ui/generator/unresolved-ct-var.rs @@ -5,10 +5,5 @@ fn main() { let _ = async { let s = std::array::from_fn(|_| ()).await; //~^ ERROR `[(); _]` is not a future - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context - //~| ERROR type inside `async` block must be known in this context }; } diff --git a/tests/ui/generator/unresolved-ct-var.stderr b/tests/ui/generator/unresolved-ct-var.stderr index ace254178b7fa..9badc1dc291ee 100644 --- a/tests/ui/generator/unresolved-ct-var.stderr +++ b/tests/ui/generator/unresolved-ct-var.stderr @@ -12,67 +12,6 @@ LL | let s = std::array::from_fn(|_| ()).await; = note: [(); _] must be a future or must implement `IntoFuture` to be awaited = note: required for `[(); _]` to implement `IntoFuture` -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var.rs:6:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var.rs:6:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var.rs:6:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var.rs:6:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var.rs:6:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var.rs:6:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var.rs:6:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var.rs:6:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error[E0698]: type inside `async` block must be known in this context - --> $DIR/unresolved-ct-var.rs:6:17 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` - | -note: the type is part of the `async` block because of this `await` - --> $DIR/unresolved-ct-var.rs:6:45 - | -LL | let s = std::array::from_fn(|_| ()).await; - | ^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0698. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/unsized-capture-across-yield.rs b/tests/ui/generator/unsized-capture-across-yield.rs new file mode 100644 index 0000000000000..7bcb0800ccfb8 --- /dev/null +++ b/tests/ui/generator/unsized-capture-across-yield.rs @@ -0,0 +1,22 @@ +#![feature(generator_trait)] +#![feature(generators)] +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::ops::Generator; + +fn capture() -> impl Generator { + let b: [u8] = *(Box::new([]) as Box<[u8]>); + move || { + println!("{:?}", &b); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + + yield; + + for elem in b.iter() {} + } +} + +fn main() { + capture(); +} diff --git a/tests/ui/generator/unsized-capture-across-yield.stderr b/tests/ui/generator/unsized-capture-across-yield.stderr new file mode 100644 index 0000000000000..8a5b968a56171 --- /dev/null +++ b/tests/ui/generator/unsized-capture-across-yield.stderr @@ -0,0 +1,23 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unsized-capture-across-yield.rs:3:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-capture-across-yield.rs:11:27 + | +LL | move || { + | -- this closure captures all values by move +LL | println!("{:?}", &b); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all values captured by value by a closure must have a statically known size + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/unsized-local-across-yield.rs b/tests/ui/generator/unsized-local-across-yield.rs new file mode 100644 index 0000000000000..f761f45c2af3a --- /dev/null +++ b/tests/ui/generator/unsized-local-across-yield.rs @@ -0,0 +1,21 @@ +#![feature(generator_trait)] +#![feature(generators)] +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::ops::Generator; + +fn across() -> impl Generator { + move || { + let b: [u8] = *(Box::new([]) as Box<[u8]>); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + + yield; + + for elem in b.iter() {} + } +} + +fn main() { + across(); +} diff --git a/tests/ui/generator/unsized-local-across-yield.stderr b/tests/ui/generator/unsized-local-across-yield.stderr new file mode 100644 index 0000000000000..1942f266e6cc4 --- /dev/null +++ b/tests/ui/generator/unsized-local-across-yield.stderr @@ -0,0 +1,21 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unsized-local-across-yield.rs:3:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-local-across-yield.rs:10:13 + | +LL | let b: [u8] = *(Box::new([]) as Box<[u8]>); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all values live across `yield` must have a statically known size + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr index 86dbad84d99d8..93c69422f00c7 100644 --- a/tests/ui/generic-associated-types/bugs/issue-100013.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr @@ -7,16 +7,6 @@ LL | | async {}.await; // a yield point LL | | } | |_____^ | -note: the lifetime defined here... - --> $DIR/issue-100013.rs:16:38 - | -LL | let x = None::>; // a type referencing GAT - | ^^ -note: ...must outlive the lifetime defined here - --> $DIR/issue-100013.rs:16:34 - | -LL | let x = None::>; // a type referencing GAT - | ^^ = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: lifetime bound not satisfied @@ -28,16 +18,6 @@ LL | | async {}.await; // a yield point LL | | } | |_____^ | -note: the lifetime `'b` defined here... - --> $DIR/issue-100013.rs:21:14 - | -LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { - | ^^ -note: ...must outlive the lifetime `'a` defined here - --> $DIR/issue-100013.rs:21:10 - | -LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { - | ^^ = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: lifetime may not live long enough @@ -62,16 +42,6 @@ LL | | async {}.await; // a yield point LL | | } | |_____^ | -note: the lifetime `'b` defined here... - --> $DIR/issue-100013.rs:28:18 - | -LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { - | ^^ -note: ...must outlive the lifetime `'a` defined here - --> $DIR/issue-100013.rs:28:10 - | -LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { - | ^^ = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: aborting due to 4 previous errors diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.stderr b/tests/ui/generic-associated-types/bugs/issue-91762.stderr index 1272c8b8ae27d..1045e80f046f2 100644 --- a/tests/ui/generic-associated-types/bugs/issue-91762.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-91762.stderr @@ -1,9 +1,10 @@ -error[E0282]: type annotations needed +error[E0284]: type annotations needed --> $DIR/issue-91762.rs:24:15 | LL | ret = ::fmap(arg); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `fmap` | + = note: cannot satisfy `<>::Base as Functor>::With<_> == Self` help: consider specifying the generic arguments | LL | ret = ::fmap::(arg); @@ -11,4 +12,4 @@ LL | ret = ::fmap::(arg); error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr index 499221637ba7f..7f535ec432c14 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -25,6 +25,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a` | LL | type Y<'a>; | ^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { diff --git a/tests/ui/generic-associated-types/issue-84931.stderr b/tests/ui/generic-associated-types/issue-84931.stderr index fffea98a449e2..fe9932c205a17 100644 --- a/tests/ui/generic-associated-types/issue-84931.stderr +++ b/tests/ui/generic-associated-types/issue-84931.stderr @@ -2,9 +2,14 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/issue-84931.rs:14:21 | LL | type Item<'a> = &'a mut T; - | ^^^^^^^^^- help: consider adding a where clause: `where T: 'a` - | | - | ...so that the reference type `&'a mut T` does not outlive the data it points at + | -- ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | type Item<'a> = &'a mut T where T: 'a; + | +++++++++++ error: aborting due to previous error diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr index 1dec7edce508c..b86e2a204b047 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr @@ -10,7 +10,7 @@ LL | async { () } | ^^^^^^^^^^^^ expected future, found `async` block | = note: expected opaque type `Foo<'_>::Fut<'a>` - found `async` block `[async block@$DIR/issue-90014-tait.rs:18:9: 18:21]` + found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18: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:17:8 | diff --git a/tests/ui/generic-associated-types/issue-91139.stderr b/tests/ui/generic-associated-types/issue-91139.stderr index d9d76adfbb552..89a4ba77e4e79 100644 --- a/tests/ui/generic-associated-types/issue-91139.stderr +++ b/tests/ui/generic-associated-types/issue-91139.stderr @@ -9,6 +9,8 @@ error: `T` does not live long enough | LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/generic-const-items/elided-lifetimes.stderr b/tests/ui/generic-const-items/elided-lifetimes.stderr index 8cd3f9ee7a918..e7df8ca5cfd99 100644 --- a/tests/ui/generic-const-items/elided-lifetimes.stderr +++ b/tests/ui/generic-const-items/elided-lifetimes.stderr @@ -28,7 +28,7 @@ LL | const I: &str = ""; | ^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 4 previous errors diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr index 22ff1b9ba7f4e..10ecd83ec53c4 100644 --- a/tests/ui/generic-const-items/inference-failure.stderr +++ b/tests/ui/generic-const-items/inference-failure.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Option` --> $DIR/inference-failure.rs:8:9 | LL | let _ = NONE; - | ^ + | ^ ---- type must be known at this point | help: consider giving this pattern a type, where the type for type parameter `T` is specified | diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr index 2cee53431a42e..14894cef77089 100644 --- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr @@ -17,6 +17,7 @@ LL | let () = K::<()>; | ^^ the trait `From<()>` is not implemented for `Infallible` | = help: the trait `From` is implemented for `Infallible` + = help: for that trait implementation, expected `!`, found `()` note: required by a bound in `K` --> $DIR/unsatisfied-bounds.rs:12:17 | @@ -48,6 +49,7 @@ LL | let _ = <() as Trait<&'static str>>::B::<()>; | ^^ the trait `From<()>` is not implemented for `Infallible` | = help: the trait `From` is implemented for `Infallible` + = help: for that trait implementation, expected `!`, found `()` note: required by a bound in `Trait::B` --> $DIR/unsatisfied-bounds.rs:21:21 | diff --git a/tests/ui/generics/issue-83556.rs b/tests/ui/generics/issue-83556.rs new file mode 100644 index 0000000000000..7cea1c8631fe9 --- /dev/null +++ b/tests/ui/generics/issue-83556.rs @@ -0,0 +1,4 @@ +struct Foo(&'a ()); +//~^ ERROR lifetime parameters must be declared prior to + +fn main() {} diff --git a/tests/ui/generics/issue-83556.stderr b/tests/ui/generics/issue-83556.stderr new file mode 100644 index 0000000000000..93affaffe60c3 --- /dev/null +++ b/tests/ui/generics/issue-83556.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-83556.rs:1:15 + | +LL | struct Foo(&'a ()); + | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>` + +error: aborting due to previous error + diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index a73c03feb8768..48703186cc634 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -24,6 +24,7 @@ LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` found enum `Option fn(Inv<'a>, Inv<'a>)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr index 33c0f7173a1d1..ef31b7266c7ef 100644 --- a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr +++ b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr @@ -1,6 +1,6 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> [async fn body@$DIR/future.rs:32:35: 34:2]: core::future::future::Future` +#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:32:35: 34:2}: core::future::future::Future` #1 [codegen_select_candidate] computing candidate for `` end of query stack diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 46f5308dd87ba..69c58c5919e11 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -15,6 +15,7 @@ LL | fn b() { want_foo2::(); } | = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 957082b6010c4..4f9ceb577c0be 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -1,4 +1,4 @@ -error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:120:22 | LL | pub struct Map { @@ -8,18 +8,18 @@ LL | pub struct Map { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `&'a mut &Map: Stream` - `&'a mut &mut Map: Stream` - `&'a mut Map: Stream` + `&'a mut &Map: Stream` + `&'a mut &mut Map: Stream` + `&'a mut Map: Stream` --> $DIR/issue-30786.rs:98:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here -error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, [closure@issue-30786.rs:131:30]>`, but its trait bounds were not satisfied +error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:132:24 | LL | pub struct Filter { @@ -32,9 +32,9 @@ LL | let count = filter.countx(); | ^^^^^^ method cannot be called due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream` - `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream` - `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream` + `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` + `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` + `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` --> $DIR/issue-30786.rs:98:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index c01ab8e347c6c..28c259be35f6f 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:11] well-formed` + = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr index 4d470ae70229f..74610b55dc373 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving ` as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V` +error[E0271]: type mismatch resolving ` as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V` --> $DIR/issue-62203-hrtb-ice.rs:39:9 | LL | let v = Unit2.m( @@ -10,7 +10,7 @@ LL | | f: |x| { ... | LL | | }, LL | | }, - | |_________^ type mismatch resolving ` as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V` + | |_________^ type mismatch resolving ` as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V` | note: expected this to be `<_ as Ty<'_>>::V` --> $DIR/issue-62203-hrtb-ice.rs:21:14 @@ -30,7 +30,7 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4` +error[E0271]: expected `{closure@issue-62203-hrtb-ice.rs:42:16}` to be a closure that returns `Unit3`, but it returns `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:39:9 | LL | let v = Unit2.m( @@ -44,7 +44,7 @@ LL | | }, LL | | }, | |_________^ expected `Unit3`, found `Unit4` | -note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>` +note: required for `L<{closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19}>` to implement `for<'r> T0<'r, (&'r u8,)>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L diff --git a/tests/ui/impl-trait/bound-normalization-fail.rs b/tests/ui/impl-trait/bound-normalization-fail.rs index 3329592478d6f..566a4a7adccb9 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.rs +++ b/tests/ui/impl-trait/bound-normalization-fail.rs @@ -39,8 +39,7 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - //~| ERROR: type mismatch + //~^ ERROR: type mismatch Foo(()) } } diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr index f04a753a0e8bd..fcac9ac34dbc3 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.stderr +++ b/tests/ui/impl-trait/bound-normalization-fail.stderr @@ -19,21 +19,12 @@ help: consider constraining the associated type `::Assoc LL | fn foo_fail>() -> impl FooLike { | ++++++++++++ -error[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:41:41 - | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` --> $DIR/bound-normalization-fail.rs:41:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` -... +LL | LL | Foo(()) | ------- return type was inferred to be `Foo<()>` here | @@ -49,7 +40,6 @@ help: consider constraining the associated type `>::As LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0658. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs new file mode 100644 index 0000000000000..9c067cb693444 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -0,0 +1,21 @@ +#![feature(rustc_attrs)] +#![rustc_variance_of_opaques] + +trait Bar<'a> { + type Assoc: From<()>; +} + +fn foo<'a, T: Bar<'a>>() -> impl Into { + //~^ ERROR [o, o] + // captures both T and 'a invariantly + () +} + +fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + //~^ ERROR [o, o, o] + // captures both T and 'a invariantly, and also duplicates `'a` + // i.e. the opaque looks like `impl Into<>::Assoc> + 'a_duplicated` + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr new file mode 100644 index 0000000000000..9d52001b02460 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -0,0 +1,14 @@ +error: [o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:8:29 + | +LL | fn foo<'a, T: Bar<'a>>() -> impl Into { + | ^^^^^^^^^^^^^^^^^^^ + +error: [o, o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:14:30 + | +LL | fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs index 156a7eb0e23d7..df47208bf3676 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs @@ -1,6 +1,3 @@ -// revisions: current next -//[next] compile-flags: -Ztrait-solver=next - #![feature(type_alias_impl_trait)] type T = impl Sized; diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr similarity index 88% rename from tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr rename to tests/ui/impl-trait/coherence-treats-tait-ambig.stderr index 61fed16294b4e..7c69c4bfe97ba 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Into` for type `Foo` - --> $DIR/coherence-treats-tait-ambig.rs:10:1 + --> $DIR/coherence-treats-tait-ambig.rs:7:1 | LL | impl Into for Foo { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/cross-return-site-inference.rs b/tests/ui/impl-trait/cross-return-site-inference.rs index 00aed2ad95a28..e1071b08c55ec 100644 --- a/tests/ui/impl-trait/cross-return-site-inference.rs +++ b/tests/ui/impl-trait/cross-return-site-inference.rs @@ -36,13 +36,13 @@ fn muh() -> Result<(), impl std::fmt::Debug> { fn muh2() -> Result<(), impl std::fmt::Debug> { return Err(From::from("foo")); - //~^ ERROR type annotations needed + //~^ ERROR cannot call associated function on trait Ok(()) } fn muh3() -> Result<(), impl std::fmt::Debug> { Err(From::from("foo")) - //~^ ERROR type annotations needed + //~^ ERROR cannot call associated function on trait } fn main() {} diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr index 766614e9e50ff..8ee3e9abf9ccb 100644 --- a/tests/ui/impl-trait/cross-return-site-inference.stderr +++ b/tests/ui/impl-trait/cross-return-site-inference.stderr @@ -9,28 +9,29 @@ help: consider specifying the generic arguments LL | Ok::<(), E>(()) | +++++++++ -error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:38:12 +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/cross-return-site-inference.rs:38:16 | LL | return Err(From::from("foo")); - | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | ^^^^^^^^^^ cannot call associated function of trait | -help: consider specifying the generic arguments +help: use a fully-qualified path to a specific available implementation | -LL | return Err::<(), E>(From::from("foo")); - | +++++++++ +LL | return Err(::from("foo")); + | +++++++++++++++++++ + -error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:44:5 +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/cross-return-site-inference.rs:44:9 | LL | Err(From::from("foo")) - | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | ^^^^^^^^^^ cannot call associated function of trait | -help: consider specifying the generic arguments +help: use a fully-qualified path to a specific available implementation | -LL | Err::<(), E>(From::from("foo")) - | +++++++++ +LL | Err(::from("foo")) + | +++++++++++++++++++ + error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0282, E0790. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/feature-self-return-type.rs b/tests/ui/impl-trait/feature-self-return-type.rs index 51877e9cc3c43..7555df1b2c709 100644 --- a/tests/ui/impl-trait/feature-self-return-type.rs +++ b/tests/ui/impl-trait/feature-self-return-type.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(impl_trait_projections)] // This test checks that we emit the correct borrowck error when `Self` or a projection is used as // a return type. See #61949 for context. diff --git a/tests/ui/impl-trait/feature-self-return-type.stderr b/tests/ui/impl-trait/feature-self-return-type.stderr index b9b8d00ce308b..e7113a9dfb1b9 100644 --- a/tests/ui/impl-trait/feature-self-return-type.stderr +++ b/tests/ui/impl-trait/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:23:22 + --> $DIR/feature-self-return-type.rs:22:22 | LL | let x = { | - borrow later stored here @@ -12,7 +12,7 @@ LL | }; | - `bar` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:63:17 + --> $DIR/feature-self-return-type.rs:62:17 | LL | let x = { | - borrow later stored here @@ -25,7 +25,7 @@ LL | }; | - `y` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:95:17 + --> $DIR/feature-self-return-type.rs:94:17 | LL | let x = { | - borrow later stored here diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index fad0b812d43dd..d3c2d5d5b9f8c 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -20,6 +20,7 @@ LL | fn ice() -> impl AsRef { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn ice() -> impl AsRef { @@ -33,6 +34,7 @@ LL | fn ice() -> impl AsRef { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | fn ice() -> impl AsRef { diff --git a/tests/ui/impl-trait/impl-subtyper.rs b/tests/ui/impl-trait/impl-subtyper.rs new file mode 100644 index 0000000000000..2d99cdd4f506e --- /dev/null +++ b/tests/ui/impl-trait/impl-subtyper.rs @@ -0,0 +1,18 @@ +// check-pass + +#![crate_type = "lib"] +fn checkpoints() -> impl Iterator { + Some(()).iter().flat_map(|_| std::iter::once(())) +} + +fn block_checkpoints() -> impl Iterator { + checkpoints() +} + +fn iter_raw() -> impl Iterator { + let mut iter = block_checkpoints(); + + (0..9).map(move |_| { + iter.next(); + }) +} diff --git a/tests/ui/impl-trait/impl-subtyper2.rs b/tests/ui/impl-trait/impl-subtyper2.rs new file mode 100644 index 0000000000000..2e0acbae68b82 --- /dev/null +++ b/tests/ui/impl-trait/impl-subtyper2.rs @@ -0,0 +1,7 @@ +// check-pass + +fn ages() -> Option { + None::> +} + +fn main(){} diff --git a/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs b/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs new file mode 100644 index 0000000000000..e62662f2f077d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs @@ -0,0 +1,13 @@ +// compile-flags: --crate-type=lib +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![deny(refining_impl_trait)] + +pub trait Tr { + fn foo() -> impl for<'a> Tr<&'a Self>; +} + +impl Tr for () { + fn foo() -> impl for<'a> Tr<&'a Self> {} +} diff --git a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs index 2a61c5cc8dffa..5de9c01e3e01f 100644 --- a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs +++ b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs @@ -9,6 +9,7 @@ trait AsyncLendingIterator { where Self: 'a; + #[allow(async_fn_in_trait)] async fn next(&mut self) -> Option>; } diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 25133214dc624..9c60cf4e72adb 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait Foo { + #[allow(async_fn_in_trait)] async fn baz(&self) -> impl Debug { "" } diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs index b0baf5bb10dd2..d3ea9fbeabc34 100644 --- a/tests/ui/impl-trait/in-trait/default-body.rs +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait Foo { + #[allow(async_fn_in_trait)] async fn baz(&self) -> &str { "" } diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs index 9c1c2b5033904..bb5718b49344c 100644 --- a/tests/ui/impl-trait/in-trait/early.rs +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn bar<'a: 'a>(&'a mut self); } diff --git a/tests/ui/impl-trait/in-trait/refine.rs b/tests/ui/impl-trait/in-trait/refine.rs index a91f9b3e72258..f00478b0bb994 100644 --- a/tests/ui/impl-trait/in-trait/refine.rs +++ b/tests/ui/impl-trait/in-trait/refine.rs @@ -45,4 +45,15 @@ impl Late for D { //~^ ERROR impl method signature does not match trait method signature } +mod unreachable { + pub trait UnreachablePub { + fn bar() -> impl Sized; + } + + struct E; + impl UnreachablePub for E { + fn bar() {} + } +} + fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine.stderr b/tests/ui/impl-trait/in-trait/refine.stderr index 29aa08e25bb91..1d9852c682cdb 100644 --- a/tests/ui/impl-trait/in-trait/refine.stderr +++ b/tests/ui/impl-trait/in-trait/refine.stderr @@ -30,8 +30,8 @@ LL | fn bar() {} = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate help: replace the return type so that it matches the trait | -LL | fn bar() -> impl Sized {} - | +++++++++++++ +LL | fn bar()-> impl Sized {} + | +++++++++++++ error: impl trait in impl method signature does not match trait method signature --> $DIR/refine.rs:22:17 diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs new file mode 100644 index 0000000000000..5e14a7f8e7213 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs @@ -0,0 +1,26 @@ +#![feature(return_position_impl_trait_in_trait)] + +trait Extend { + fn extend<'a: 'a>(_: &'a str) -> (impl Sized + 'a, &'static str); +} + +impl Extend for () { + fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + //~^ ERROR in type `&'static &'a ()`, reference has a longer lifetime than the data it references + where + 'a: 'static, + { + (None, s) + } +} + +// This indirection is not necessary for reproduction, +// but it makes this test future-proof against #114936. +fn extend(s: &str) -> &'static str { + ::extend(s).1 +} + +fn main() { + let use_after_free = extend::<()>(&String::from("temporary")); + println!("{}", use_after_free); +} diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr new file mode 100644 index 0000000000000..1d947310e120a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr @@ -0,0 +1,16 @@ +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:38 + | +LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:15 + | +LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.rs b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.rs new file mode 100644 index 0000000000000..c1885af4e5e1f --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.rs @@ -0,0 +1,23 @@ +#![feature(return_position_impl_trait_in_trait)] + +trait Extend { + fn extend(_: &str) -> (impl Sized + '_, &'static str); +} + +impl Extend for () { + fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { + //~^ ERROR in type `&'static &()`, reference has a longer lifetime than the data it references + (None, s) + } +} + +// This indirection is not necessary for reproduction, +// but it makes this test future-proof against #114936. +fn extend(s: &str) -> &'static str { + ::extend(s).1 +} + +fn main() { + let use_after_free = extend::<()>(&String::from("temporary")); + println!("{}", use_after_free); +} diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr new file mode 100644 index 0000000000000..7b63e72acbf21 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr @@ -0,0 +1,16 @@ +error[E0491]: in type `&'static &()`, reference has a longer lifetime than the data it references + --> $DIR/rpitit-hidden-types-self-implied-wf.rs:8:27 + | +LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the anonymous lifetime defined here + --> $DIR/rpitit-hidden-types-self-implied-wf.rs:8:18 + | +LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed index d9f775a6c8464..58d83384a238c 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed @@ -4,12 +4,15 @@ #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn foo(); + #[allow(async_fn_in_trait)] async fn bar() -> i32; fn test(&self) -> impl Sized + '_; + #[allow(async_fn_in_trait)] async fn baz(&self) -> &i32; } diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs index 26979b5149b06..c27229806e130 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs @@ -4,12 +4,15 @@ #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn foo(); + #[allow(async_fn_in_trait)] async fn bar() -> i32; fn test(&self) -> impl Sized + '_; + #[allow(async_fn_in_trait)] async fn baz(&self) -> &i32; } diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index 44f98896eb384..29f6bad86dc82 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -1,15 +1,15 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz` - --> $DIR/suggest-missing-item.rs:18:1 + --> $DIR/suggest-missing-item.rs:21:1 | LL | async fn foo(); | --------------- `foo` from trait -LL | +... LL | async fn bar() -> i32; | ---------------------- `bar` from trait LL | LL | fn test(&self) -> impl Sized + '_; | ---------------------------------- `test` from trait -LL | +... LL | async fn baz(&self) -> &i32; | ---------------------------- `baz` from trait ... diff --git a/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr b/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr deleted file mode 100644 index 477c964bd40fd..0000000000000 --- a/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:17:9 - | -LL | async {} - | ^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr b/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr deleted file mode 100644 index 477c964bd40fd..0000000000000 --- a/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:17:9 - | -LL | async {} - | ^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/impl-trait/issue-55872-2.rs b/tests/ui/impl-trait/issue-55872-2.rs index 7a5cb3b3dfcbe..8a96fdc5c63d1 100644 --- a/tests/ui/impl-trait/issue-55872-2.rs +++ b/tests/ui/impl-trait/issue-55872-2.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 #![feature(impl_trait_in_assoc_type)] @@ -16,7 +13,7 @@ impl Bar for S { fn foo() -> Self::E { async {} //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //[drop_tracking_mir]~^^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr b/tests/ui/impl-trait/issue-55872-2.stderr similarity index 71% rename from tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr rename to tests/ui/impl-trait/issue-55872-2.stderr index c14bb5cc9142d..b5b7f293a40b2 100644 --- a/tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr +++ b/tests/ui/impl-trait/issue-55872-2.stderr @@ -1,14 +1,16 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:17:9 + --> $DIR/issue-55872-2.rs:14:9 | LL | async {} | ^^^^^^^^ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:17:9 + --> $DIR/issue-55872-2.rs:14:9 | LL | async {} | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr index 8279889743344..b542b61419960 100644 --- a/tests/ui/impl-trait/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `[async block@$DIR/issue-55872-3.rs:15:9: 15:17]: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}: Copy` is not satisfied --> $DIR/issue-55872-3.rs:13:20 | LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/issue-55872-3.rs:15:9: 15:17]` + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}` error: aborting due to previous error diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr index a8400080e5a18..3c32f1794a0e0 100644 --- a/tests/ui/impl-trait/issue-99073.stderr +++ b/tests/ui/impl-trait/issue-99073.stderr @@ -10,7 +10,7 @@ error: concrete type differs from previous defining opaque type use --> $DIR/issue-99073.rs:6:13 | LL | move || f(fix(&f)) - | ^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G` + | ^^^^^^^ expected `{closure@$DIR/issue-99073.rs:6:3: 6:10}`, got `G` | note: previous use here --> $DIR/issue-99073.rs:5:36 diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs index 3024fedf7b5fb..ccf2767012e6d 100644 --- a/tests/ui/impl-trait/issues/issue-54600.rs +++ b/tests/ui/impl-trait/issues/issue-54600.rs @@ -2,6 +2,6 @@ use std::fmt::Debug; fn main() { let x: Option = Some(44_u32); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types println!("{:?}", x); } diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index 7ef063af95222..9a8e3675b9569 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-54600.rs:4:19 | LL | let x: Option = Some(44_u32); diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs index 8f1e0ece03a62..910d23f1d9386 100644 --- a/tests/ui/impl-trait/issues/issue-54840.rs +++ b/tests/ui/impl-trait/issues/issue-54840.rs @@ -3,5 +3,5 @@ use std::ops::Add; fn main() { let i: i32 = 0; let j: &impl Add = &i; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index 1d1316f0e110b..67cabf4495067 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-54840.rs:5:13 | LL | let j: &impl Add = &i; diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs index e5865d0dfff34..f1d7b94ef2dbd 100644 --- a/tests/ui/impl-trait/issues/issue-58504.rs +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -8,5 +8,5 @@ fn mk_gen() -> impl Generator { fn main() { let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index 26ec2a4f9cfe5..1be676ee075d3 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-58504.rs:10:16 | LL | let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs index 68cfcd9ba4f9e..5d5566860c0fc 100644 --- a/tests/ui/impl-trait/issues/issue-58956.rs +++ b/tests/ui/impl-trait/issues/issue-58956.rs @@ -5,9 +5,9 @@ impl Lam for B {} pub struct Wrap(T); const _A: impl Lam = { - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types let x: Wrap = Wrap(B); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types x.0 }; diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr index 2b4d0abdffca8..5ee33352afa2a 100644 --- a/tests/ui/impl-trait/issues/issue-58956.stderr +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -1,10 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/issue-58956.rs:7:11 | LL | const _A: impl Lam = { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-58956.rs:9:17 | LL | let x: Wrap = Wrap(B); diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index d872291c87054..8d969e8e0f3dc 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied LL | WrongImpl::foo(0i32); | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` | - = help: the trait `Raw<[T]>` is implemented for `RawImpl` + = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 | @@ -42,7 +42,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` | - = help: the trait `Raw<[T]>` is implemented for `RawImpl` + = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>` + = help: for that trait implementation, expected `[()]`, found `()` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 | diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs index f8ae18bacd67d..c24259a71eb22 100644 --- a/tests/ui/impl-trait/issues/issue-70971.rs +++ b/tests/ui/impl-trait/issues/issue-70971.rs @@ -1,4 +1,4 @@ fn main() { let x : (impl Copy,) = (true,); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index d066256bfb09d..5609f8b9b012c 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-70971.rs:2:14 | LL | let x : (impl Copy,) = (true,); diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr index d43e9fee0b359..f8e85f7ae0008 100644 --- a/tests/ui/impl-trait/issues/issue-74282.stderr +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -14,7 +14,7 @@ LL | | }) | |_____^ expected opaque type, found closure | = note: expected opaque type `Closure` - found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]` + found closure `{closure@$DIR/issue-74282.rs:8:15: 8:17}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object note: tuple struct defined here diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr index 6db603e775175..8817eb7d243fb 100644 --- a/tests/ui/impl-trait/issues/issue-78722-2.stderr +++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr @@ -7,7 +7,7 @@ LL | let f: F = async { 1 }; = note: see issue #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 `()` +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 { diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr index 36340a0bab41a..5ad659697314a 100644 --- a/tests/ui/impl-trait/issues/issue-78722.stderr +++ b/tests/ui/impl-trait/issues/issue-78722.stderr @@ -7,7 +7,7 @@ LL | let f: F = async { 1 }; = note: see issue #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:10:13: 10:21]` to be a future that resolves to `u8`, but it resolves to `()` +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 { diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs index da53594f3d091..22c66491ce988 100644 --- a/tests/ui/impl-trait/issues/issue-79099.rs +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -1,7 +1,7 @@ struct Bug { V1: [(); { let f: impl core::future::Future = async { 1 }; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types //~| expected identifier 1 }], diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr index 580250a62fecd..82fc03c61b3b3 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -9,7 +9,7 @@ LL | let f: impl core::future::Future = async { 1 }; = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-79099.rs:3:16 | LL | let f: impl core::future::Future = async { 1 }; diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs index 344f359529b61..3224145bffeb4 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -1,8 +1,8 @@ struct Foo(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types type Result = std::result::Result; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // should not cause ICE fn x() -> Foo { diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr index 656bd04706124..56be4577d51a0 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -1,10 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16 | LL | struct Foo(T); | ^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20 | LL | type Result = std::result::Result; diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index 3c39aa6ce5bb9..b4be16ff0420e 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `RaceBuilder>` --> $DIR/issue-84073.rs:32:16 | LL | Race::new(|race| race.when()); - | ^^^^ + | ^^^^ ---- type must be known at this point | help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified | diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs index a0b73743a2b2d..77d27d7c06b6c 100644 --- a/tests/ui/impl-trait/issues/issue-84919.rs +++ b/tests/ui/impl-trait/issues/issue-84919.rs @@ -3,7 +3,7 @@ impl Trait for () {} fn foo<'a: 'a>() { let _x: impl Trait = (); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 36010fdef36c3..20b131b8bd200 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-84919.rs:5:13 | LL | let _x: impl Trait = (); diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs index e6e95771400d3..49f8944ac4af0 100644 --- a/tests/ui/impl-trait/issues/issue-86642.rs +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -1,5 +1,5 @@ static x: impl Fn(&str) -> Result<&str, ()> = move |source| { - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types let res = (move |source| Ok(source))(source); let res = res.or((move |source| Ok(source))(source)); res diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr index b6f8a54f35ae8..6d3be3fff0e10 100644 --- a/tests/ui/impl-trait/issues/issue-86642.stderr +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/issue-86642.rs:1:11 | LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs index aeb8f83326e4d..eb44020ac0e72 100644 --- a/tests/ui/impl-trait/issues/issue-87295.rs +++ b/tests/ui/impl-trait/issues/issue-87295.rs @@ -14,5 +14,5 @@ impl Struct { fn main() { let _do_not_waste: Struct> = Struct::new(()); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index ec59b719c10e1..3fe4ee73c80c3 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-87295.rs:16:31 | LL | let _do_not_waste: Struct> = Struct::new(()); diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 55e3cd95064ba..c60fe08c5d7c5 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -104,7 +104,7 @@ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- ---------------- opaque type defined here | | - | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here + | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13}` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -117,9 +117,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:43:5 | LL | x - | ^ ...so that the type `T` will meet its required lifetime bounds + | ^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | +++++++++ diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.stderr b/tests/ui/impl-trait/nested-return-type2-tait2.stderr index b85bb5efd100a..125262b96e815 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait2.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait2.stderr @@ -5,7 +5,7 @@ LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `Sendable` | = help: the trait `Duh` is implemented for `i32` -note: required for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7]` to implement `Trait` +note: required for `{closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7}` to implement `Trait` --> $DIR/nested-return-type2-tait2.rs:14:31 | LL | impl R> Trait for F { diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.stderr b/tests/ui/impl-trait/nested-return-type2-tait3.stderr index 19fd3c134acda..c2332b6e4bdd5 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait3.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait3.stderr @@ -5,7 +5,7 @@ LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `impl Send` | = help: the trait `Duh` is implemented for `i32` -note: required for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7]` to implement `Trait` +note: required for `{closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7}` to implement `Trait` --> $DIR/nested-return-type2-tait3.rs:14:31 | LL | impl R> Trait for F { diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr index 907822ebbc3ab..a1e2d227ff385 100644 --- a/tests/ui/impl-trait/nested-return-type4.stderr +++ b/tests/ui/impl-trait/nested-return-type4.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Future` captures lifeti LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { | -- --------------------------------------------- opaque type defined here | | - | hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here + | hidden type `{async block@$DIR/nested-return-type4.rs:4:5: 4:31}` captures the lifetime `'s` as defined here LL | async move { let _s = s; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs index e95fab3b65057..c036b9e367a17 100644 --- a/tests/ui/impl-trait/nested_impl_trait.rs +++ b/tests/ui/impl-trait/nested_impl_trait.rs @@ -9,7 +9,7 @@ fn bad_in_ret_position(x: impl Into) -> impl Into { x } fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed -//~| `impl Trait` only allowed in function and inherent method return types +//~| `impl Trait` only allowed in function and inherent method argument and return types fn bad_in_arg_position(_: impl Into) { } //~^ ERROR nested `impl Trait` is not allowed diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index ffe84b8e86fc4..f1cafd958b05e 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -34,7 +34,7 @@ LL | fn bad(x: impl Into) -> impl Into { x } | | nested `impl Trait` here | outer `impl Trait` -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/nested_impl_trait.rs:10:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 5fbba9a85caf3..ada8fd7fa50ee 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,25 +1,8 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/normalize-tait-in-const.rs:26:5 - | -LL | fun(filter_positive()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { - | ++++++++++++++++++++++++++++++++++++ - -error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/normalize-tait-in-const.rs:25:79 +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/normalize-tait-in-const.rs:25:42 | LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { - | ^^^ the destructor for this type cannot be evaluated in constant functions -LL | fun(filter_positive()); -LL | } - | - value is dropped here + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs b/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs new file mode 100644 index 0000000000000..3e3bc09a62aa8 --- /dev/null +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs @@ -0,0 +1,27 @@ +// edition: 2021 + +use std::future::Future; + +async fn bop() { + fold(run(), |mut foo| async move { + &mut foo.bar; + }) +} + +fn fold(_: Foo, f: F) +where + F: FnMut(Foo) -> Fut, +{ + loop {} +} + +struct Foo { + bar: Vec, +} + +fn run() -> Foo> { + //~^ ERROR type annotations needed + loop {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr new file mode 100644 index 0000000000000..2347805343c93 --- /dev/null +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr @@ -0,0 +1,11 @@ +error[E0283]: type annotations needed + --> $DIR/opaque-cast-field-access-in-future.rs:22:17 + | +LL | fn run() -> Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `_: Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-trait/recursive-generator.rs b/tests/ui/impl-trait/recursive-generator.rs index e876f0fb43f65..000af70c4540e 100644 --- a/tests/ui/impl-trait/recursive-generator.rs +++ b/tests/ui/impl-trait/recursive-generator.rs @@ -7,7 +7,6 @@ fn foo() -> impl Generator { //~| NOTE recursive opaque type //~| NOTE in this expansion of desugaring of || { - //~^ NOTE returning here let mut gen = Box::pin(foo()); //~^ NOTE generator captures itself here let mut r = gen.as_mut().resume(()); diff --git a/tests/ui/impl-trait/recursive-generator.stderr b/tests/ui/impl-trait/recursive-generator.stderr index e23fd4b4a85e5..86e193d9599a1 100644 --- a/tests/ui/impl-trait/recursive-generator.stderr +++ b/tests/ui/impl-trait/recursive-generator.stderr @@ -1,18 +1,11 @@ error[E0720]: cannot resolve opaque type --> $DIR/recursive-generator.rs:5:13 | -LL | fn foo() -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type +LL | fn foo() -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type ... -LL | / || { -LL | | -LL | | let mut gen = Box::pin(foo()); - | | ------- generator captures itself here -LL | | -... | -LL | | } -LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-generator.rs:9:5: 9:7]` +LL | let mut gen = Box::pin(foo()); + | ------- generator captures itself here error: aborting due to previous error diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr deleted file mode 100644 index 43118ae38540f..0000000000000 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:11:22 - | -LL | fn option(i: i32) -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | if i < 0 { None } else { Some((option(i - 1), i)) } - | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>` - | | - | returning here with type `Option<(impl Sized, i32)>` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:16:15 - | -LL | fn tuple() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (tuple(),) - | ---------- returning here with type `(impl Sized,)` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:21:15 - | -LL | fn array() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | [array()] - | --------- returning here with type `[impl Sized; 1]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:26:13 - | -LL | fn ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | &ptr() as *const _ - | ------------------ returning here with type `*const impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:31:16 - | -LL | fn fn_ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | fn_ptr as fn() -> _ - | ------------------- returning here with type `fn() -> impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:36:25 - | -LL | fn closure_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:44:29 - | -LL | fn closure_ref_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | &x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:52:21 - | -LL | fn closure_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || closure_sig() - | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:57:23 - | -LL | fn generator_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || generator_sig() - | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:62:27 - | -LL | fn generator_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | yield; -LL | | x; - | | - generator captures itself here -LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:71:35 - | -LL | fn substs_change() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (substs_change::<&T>(),) - | ------------------------ returning here with type `(impl Sized,)` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:76:24 - | -LL | fn generator_hold() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | / move || { -LL | | let x = generator_hold(); - | | - generator captures itself here -LL | | yield; -LL | | x; -LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:90:26 - | -LL | fn mutual_recursion() -> impl Sync { - | ^^^^^^^^^ recursive opaque type -LL | -LL | mutual_recursion_b() - | -------------------- returning here with type `impl Sized` -... -LL | fn mutual_recursion_b() -> impl Sized { - | ---------- returning this opaque type `impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:95:28 - | -LL | fn mutual_recursion() -> impl Sync { - | --------- returning this opaque type `impl Sync` -... -LL | fn mutual_recursion_b() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | mutual_recursion() - | ------------------ returning here with type `impl Sync` - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr deleted file mode 100644 index 43118ae38540f..0000000000000 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:11:22 - | -LL | fn option(i: i32) -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | if i < 0 { None } else { Some((option(i - 1), i)) } - | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>` - | | - | returning here with type `Option<(impl Sized, i32)>` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:16:15 - | -LL | fn tuple() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (tuple(),) - | ---------- returning here with type `(impl Sized,)` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:21:15 - | -LL | fn array() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | [array()] - | --------- returning here with type `[impl Sized; 1]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:26:13 - | -LL | fn ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | &ptr() as *const _ - | ------------------ returning here with type `*const impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:31:16 - | -LL | fn fn_ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | fn_ptr as fn() -> _ - | ------------------- returning here with type `fn() -> impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:36:25 - | -LL | fn closure_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:44:29 - | -LL | fn closure_ref_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | &x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:52:21 - | -LL | fn closure_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || closure_sig() - | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:57:23 - | -LL | fn generator_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || generator_sig() - | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:62:27 - | -LL | fn generator_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | yield; -LL | | x; - | | - generator captures itself here -LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:71:35 - | -LL | fn substs_change() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (substs_change::<&T>(),) - | ------------------------ returning here with type `(impl Sized,)` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:76:24 - | -LL | fn generator_hold() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | / move || { -LL | | let x = generator_hold(); - | | - generator captures itself here -LL | | yield; -LL | | x; -LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:90:26 - | -LL | fn mutual_recursion() -> impl Sync { - | ^^^^^^^^^ recursive opaque type -LL | -LL | mutual_recursion_b() - | -------------------- returning here with type `impl Sized` -... -LL | fn mutual_recursion_b() -> impl Sized { - | ---------- returning this opaque type `impl Sized` - -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:95:28 - | -LL | fn mutual_recursion() -> impl Sync { - | --------- returning this opaque type `impl Sync` -... -LL | fn mutual_recursion_b() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | mutual_recursion() - | ------------------ returning here with type `impl Sync` - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs index 630372e13ed58..ffc0cd9d10c34 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -1,7 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - // Test that impl trait does not allow creating recursive types that are // otherwise forbidden. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr similarity index 74% rename from tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr rename to tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index 9c67f17e96358..1d919fb524049 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -1,5 +1,5 @@ error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:11:22 + --> $DIR/recursive-impl-trait-type-indirect.rs:7:22 | LL | fn option(i: i32) -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -10,7 +10,7 @@ LL | if i < 0 { None } else { Some((option(i - 1), i)) } | returning here with type `Option<(impl Sized, i32)>` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:16:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:12:15 | LL | fn tuple() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -19,7 +19,7 @@ LL | (tuple(),) | ---------- returning here with type `(impl Sized,)` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:21:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:17:15 | LL | fn array() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -28,7 +28,7 @@ LL | [array()] | --------- returning here with type `[impl Sized; 1]` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:26:13 + --> $DIR/recursive-impl-trait-type-indirect.rs:22:13 | LL | fn ptr() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -37,7 +37,7 @@ LL | &ptr() as *const _ | ------------------ returning here with type `*const impl Sized` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:31:16 + --> $DIR/recursive-impl-trait-type-indirect.rs:27:16 | LL | fn fn_ptr() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -46,7 +46,7 @@ LL | fn_ptr as fn() -> _ | ------------------- returning here with type `fn() -> impl Sized` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:36:25 + --> $DIR/recursive-impl-trait-type-indirect.rs:32:25 | LL | fn closure_capture() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -55,10 +55,10 @@ LL | / move || { LL | | x; | | - closure captures itself here LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]` + | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:44:29 + --> $DIR/recursive-impl-trait-type-indirect.rs:40:29 | LL | fn closure_ref_capture() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -67,28 +67,28 @@ LL | / move || { LL | | &x; | | - closure captures itself here LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]` + | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:52:21 + --> $DIR/recursive-impl-trait-type-indirect.rs:48:21 | LL | fn closure_sig() -> impl Sized { | ^^^^^^^^^^ recursive opaque type LL | LL | || closure_sig() - | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]` + | ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:57:23 + --> $DIR/recursive-impl-trait-type-indirect.rs:53:23 | LL | fn generator_sig() -> impl Sized { | ^^^^^^^^^^ recursive opaque type LL | LL | || generator_sig() - | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]` + | ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:62:27 + --> $DIR/recursive-impl-trait-type-indirect.rs:58:27 | LL | fn generator_capture() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -98,10 +98,10 @@ LL | | yield; LL | | x; | | - generator captures itself here LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]` + | |_____- returning here with type `{generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:71:35 + --> $DIR/recursive-impl-trait-type-indirect.rs:67:35 | LL | fn substs_change() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -110,7 +110,7 @@ LL | (substs_change::<&T>(),) | ------------------------ returning here with type `(impl Sized,)` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:76:24 + --> $DIR/recursive-impl-trait-type-indirect.rs:72:24 | LL | fn generator_hold() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -119,7 +119,7 @@ LL | let x = generator_hold(); | - generator captures itself here error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:90:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:86:26 | LL | fn mutual_recursion() -> impl Sync { | ^^^^^^^^^ recursive opaque type @@ -131,7 +131,7 @@ LL | fn mutual_recursion_b() -> impl Sized { | ---------- returning this opaque type `impl Sized` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:95:28 + --> $DIR/recursive-impl-trait-type-indirect.rs:91:28 | LL | fn mutual_recursion() -> impl Sync { | --------- returning this opaque type `impl Sync` diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr index 488cb821c1051..4be244068d226 100644 --- a/tests/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Iterator` captures lifetime that LL | fn iter_values_anon(&self) -> impl Iterator { | ----- ----------------------- opaque type defined here | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here + | hidden type `Map, {closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30}>` captures the anonymous lifetime defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -19,7 +19,7 @@ error[E0700]: hidden type for `impl Iterator` captures lifetime that LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -- ----------------------- opaque type defined here | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here + | hidden type `Map, {closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30}>` captures the lifetime `'a` as defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/impl-trait/type_parameters_captured.stderr b/tests/ui/impl-trait/type_parameters_captured.stderr index fb502cfdd2b35..46859296fb8b4 100644 --- a/tests/ui/impl-trait/type_parameters_captured.stderr +++ b/tests/ui/impl-trait/type_parameters_captured.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/type_parameters_captured.rs:8:5 | LL | x - | ^ ...so that the type `T` will meet its required lifetime bounds + | ^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn foo(x: T) -> impl Any + 'static { | +++++++++ diff --git a/tests/ui/impl-trait/unactionable_diagnostic.fixed b/tests/ui/impl-trait/unactionable_diagnostic.fixed index 6c2505177fef8..d446512ffc281 100644 --- a/tests/ui/impl-trait/unactionable_diagnostic.fixed +++ b/tests/ui/impl-trait/unactionable_diagnostic.fixed @@ -14,7 +14,7 @@ fn foo<'x, P>( } pub fn bar<'t, T: 't>( - //~^ HELP: consider adding an explicit lifetime bound... + //~^ HELP: consider adding an explicit lifetime bound post: T, x: &'t Foo, ) -> &'t impl Trait { diff --git a/tests/ui/impl-trait/unactionable_diagnostic.rs b/tests/ui/impl-trait/unactionable_diagnostic.rs index bce35cbdd0d38..76b9a62ca1338 100644 --- a/tests/ui/impl-trait/unactionable_diagnostic.rs +++ b/tests/ui/impl-trait/unactionable_diagnostic.rs @@ -14,7 +14,7 @@ fn foo<'x, P>( } pub fn bar<'t, T>( - //~^ HELP: consider adding an explicit lifetime bound... + //~^ HELP: consider adding an explicit lifetime bound post: T, x: &'t Foo, ) -> &'t impl Trait { diff --git a/tests/ui/impl-trait/unactionable_diagnostic.stderr b/tests/ui/impl-trait/unactionable_diagnostic.stderr index a32004cda1a6f..4df7f45c3b37e 100644 --- a/tests/ui/impl-trait/unactionable_diagnostic.stderr +++ b/tests/ui/impl-trait/unactionable_diagnostic.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/unactionable_diagnostic.rs:21:5 | +LL | pub fn bar<'t, T>( + | -- the parameter type `T` must be valid for the lifetime `'t` as defined here... +... LL | foo(post, x) | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | pub fn bar<'t, T: 't>( | ++++ diff --git a/tests/ui/impl-trait/where-allowed-2.stderr b/tests/ui/impl-trait/where-allowed-2.stderr index 2b328c01c8729..b3765ac1a541f 100644 --- a/tests/ui/impl-trait/where-allowed-2.stderr +++ b/tests/ui/impl-trait/where-allowed-2.stderr @@ -1,9 +1,11 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/where-allowed-2.rs:3:30 | LL | fn in_adt_in_return() -> Vec { panic!() } | ^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `_: Debug` error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs index 509d2716649e5..d3fab326e748a 100644 --- a/tests/ui/impl-trait/where-allowed.rs +++ b/tests/ui/impl-trait/where-allowed.rs @@ -16,47 +16,47 @@ fn in_adt_in_parameters(_: Vec) { panic!() } // Disallowed fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR nested `impl Trait` is not allowed // Allowed @@ -64,11 +64,11 @@ fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Allowed @@ -81,22 +81,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator { // Disallowed struct InBraceStructField { x: impl Debug } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed struct InAdtInBraceStructField { x: Vec } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed struct InTupleStructField(impl Debug); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed enum InEnum { InBraceVariant { x: impl Debug }, - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types InTupleVariant(impl Debug), - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -107,7 +107,7 @@ trait InTraitDefnParameters { // Disallowed trait InTraitDefnReturn { fn in_return() -> impl Debug; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed and disallowed in trait impls @@ -124,7 +124,7 @@ impl DummyTrait for () { // Allowed fn in_trait_impl_return() -> impl Debug { () } - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -137,10 +137,10 @@ impl DummyType { // Disallowed extern "C" { fn in_foreign_parameters(_: impl Debug); - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types fn in_foreign_return() -> impl Debug; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -156,97 +156,97 @@ type InTypeAlias = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable type InReturnInTypeAlias = fn() -> impl Debug; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR `impl Trait` in type aliases is unstable // Disallowed in impl headers impl PartialEq for () { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in impl headers impl PartialEq<()> for impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in inherent impls impl impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in inherent impls struct InInherentImplAdt { t: T } impl InInherentImplAdt { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in where clauses fn in_fn_where_clause() where impl Debug: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed in where clauses fn in_adt_in_fn_where_clause() where Vec: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_trait_parameter_in_fn_where_clause() where T: PartialEq -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_Fn_parameter_in_fn_where_clause() where T: Fn(impl Debug) -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_Fn_return_in_fn_where_clause() where T: Fn() -> impl Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed struct InStructGenericParamDefault(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed enum InEnumGenericParamDefault { Variant(T) } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed trait InTraitGenericParamDefault {} -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed type InTypeAliasGenericParamDefault = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed impl T {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR no nominal type found // Disallowed fn in_method_generic_param_default(_: T) {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types fn main() { let _in_local_variable: impl Fn() = || {}; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types let _in_return_in_local_variable = || -> impl Fn() { || {} }; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 3e29343797554..bd7c9a947932d 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -43,109 +43,109 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = note: see issue #63063 for more information = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params --> $DIR/where-allowed.rs:18:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:22:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params --> $DIR/where-allowed.rs:26:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:30:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:34:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:38:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:42:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:49:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:54:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:58:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:66:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:70:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:83:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:87:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:91:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:96:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:98:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/where-allowed.rs:109:23 | LL | fn in_return() -> impl Debug; @@ -154,7 +154,7 @@ LL | fn in_return() -> impl Debug; = note: see issue #91611 for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types --> $DIR/where-allowed.rs:126:34 | LL | fn in_trait_impl_return() -> impl Debug { () } @@ -163,121 +163,121 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = note: see issue #91611 for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` params --> $DIR/where-allowed.rs:139:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` return types --> $DIR/where-allowed.rs:142:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:158:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in traits +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in traits --> $DIR/where-allowed.rs:163:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:168:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:173:6 | LL | impl impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:179:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:185:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:192:15 | LL | where Vec: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:199:24 | LL | where T: PartialEq | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:206:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:213:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:219:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:223:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:227:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:231:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:235:11 | LL | impl T {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:242:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/where-allowed.rs:248:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in closure return types --> $DIR/where-allowed.rs:250:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index 6c7d79174daf6..2731ed2ba86d3 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -60,6 +60,7 @@ note: `date_range` could also refer to the function imported here LL | use prelude::*; | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 4 warnings emitted diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index 788fcc830ae9a..30d2373652b4c 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -38,6 +38,7 @@ LL | #[derive(NonExistent)] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot determine resolution for the derive macro `NonExistent` --> $DIR/issue-55457.rs:5:10 @@ -46,6 +47,7 @@ LL | #[derive(NonExistent)] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index e020d0298757d..2cb212a013960 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -5,7 +5,8 @@ LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec<{integer}>` to implement `Index` error: aborting due to previous error diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 7a741cfc7def4..6ea6bb600e944 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -5,7 +5,8 @@ LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` error[E0308]: mismatched types diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr index b706cd2bc36e8..98639f307fbfd 100644 --- a/tests/ui/inference/cannot-infer-closure-circular.stderr +++ b/tests/ui/inference/cannot-infer-closure-circular.stderr @@ -3,6 +3,9 @@ error[E0282]: type annotations needed for `Result<(), E>` | LL | let x = |r| { | ^ +LL | let v = r?; +LL | Ok(v) + | ----- type must be known at this point | help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified | diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr index 4962b21f9fdb4..2819329275d17 100644 --- a/tests/ui/inference/issue-104649.stderr +++ b/tests/ui/inference/issue-104649.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `A $DIR/issue-104649.rs:24:9 | LL | let a = A(Result::Ok(Result::Ok(()))); - | ^ + | ^ -------------- type must be known at this point | help: consider giving `a` an explicit type, where the type for type parameter `E` is specified | diff --git a/tests/ui/inference/issue-71584.rs b/tests/ui/inference/issue-71584.rs index 7bf3ed60ec104..c96c32d5c0a09 100644 --- a/tests/ui/inference/issue-71584.rs +++ b/tests/ui/inference/issue-71584.rs @@ -1,3 +1,4 @@ +// ignore-windows different list of satisfying impls fn main() { let n: u32 = 1; let mut d: u64 = 2; diff --git a/tests/ui/inference/issue-71584.stderr b/tests/ui/inference/issue-71584.stderr index 6ddb7657301cd..22c0f113d6ab8 100644 --- a/tests/ui/inference/issue-71584.stderr +++ b/tests/ui/inference/issue-71584.stderr @@ -1,5 +1,5 @@ error[E0284]: type annotations needed - --> $DIR/issue-71584.rs:4:15 + --> $DIR/issue-71584.rs:5:15 | LL | d = d % n.into(); | - ^^^^ diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr index 225558805e08a..6c93241ea07cd 100644 --- a/tests/ui/inference/issue-72690.stderr +++ b/tests/ui/inference/issue-72690.stderr @@ -24,16 +24,15 @@ help: try using a fully qualified path to specify the expected types LL | String::from(>::as_ref("x")); | ++++++++++++++++++++++++++ ~ -error[E0282]: type annotations needed - --> $DIR/issue-72690.rs:12:6 +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:12:9 | LL | |x| String::from("x".as_ref()); - | ^ - | -help: consider giving this closure parameter an explicit type + | ^^^^^^ cannot infer type for reference `&_` | -LL | |x: /* Type */| String::from("x".as_ref()); - | ++++++++++++ + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; error[E0283]: type annotations needed --> $DIR/issue-72690.rs:12:26 @@ -225,5 +224,4 @@ LL | String::from(>::as_ref("x")); error: aborting due to 17 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/multiple-impl-apply.rs b/tests/ui/inference/multiple-impl-apply.rs new file mode 100644 index 0000000000000..314fe0f2ae510 --- /dev/null +++ b/tests/ui/inference/multiple-impl-apply.rs @@ -0,0 +1,48 @@ +struct Foo { + inner: u32, +} + +struct Bar { + inner: u32, +} + +#[derive(Clone, Copy)] +struct Baz { + inner: u32, +} + +impl From for Bar { + fn from(other: Baz) -> Self { + Self { + inner: other.inner, + } + } +} + +impl From for Foo { + fn from(other: Baz) -> Self { + Self { + inner: other.inner, + } + } +} + +fn main() { + let x: Baz = Baz { inner: 42 }; + + // DOESN'T Compile: Multiple options! + let y = x.into(); //~ ERROR E0283 + + let y_1: Foo = x.into(); + let y_2: Bar = x.into(); + + let z_1 = Foo::from(y_1); + let z_2 = Bar::from(y_2); + + // No type annotations needed, the compiler KNOWS the type must be `Foo`! + let m = magic_foo(x); +} + +fn magic_foo(arg: Baz) -> Foo { + arg.into() +} diff --git a/tests/ui/inference/multiple-impl-apply.stderr b/tests/ui/inference/multiple-impl-apply.stderr new file mode 100644 index 0000000000000..ec49e15201af9 --- /dev/null +++ b/tests/ui/inference/multiple-impl-apply.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed + --> $DIR/multiple-impl-apply.rs:34:9 + | +LL | let y = x.into(); + | ^ ---- type must be known at this point + | +note: multiple `impl`s satisfying `_: From` found + --> $DIR/multiple-impl-apply.rs:14:1 + | +LL | impl From for Bar { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl From for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: required for `Baz` to implement `Into<_>` +help: consider giving `y` an explicit type + | +LL | let y: /* Type */ = x.into(); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs index fc79e6201bdb8..8960f870c39f4 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.rs +++ b/tests/ui/inference/need_type_info/concrete-impl.rs @@ -14,6 +14,4 @@ fn main() { >::method(); //~^ ERROR type annotations needed //~| NOTE cannot infer type of the type parameter `A` - //~| ERROR type annotations needed - //~| NOTE infer type of the type parameter `A` } diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr index 74c3f6cd5cfad..6b86753caf992 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.stderr +++ b/tests/ui/inference/need_type_info/concrete-impl.stderr @@ -1,9 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/concrete-impl.rs:14:5 - | -LL | >::method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous` - error[E0283]: type annotations needed --> $DIR/concrete-impl.rs:14:5 | @@ -19,7 +13,6 @@ LL | LL | impl Ambiguous for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr index 0ec219415ab07..9ca94cd58df32 100644 --- a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr +++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr @@ -1,9 +1,17 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:10:16 | LL | (S {}).owo(None) - | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | --- ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | | + | required by a bound introduced by this call | + = note: cannot satisfy `_: T` +note: required by a bound in `S::owo` + --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:6:35 + | +LL | fn owo(&self, _: Option<&impl T>) {} + | ^ required by this bound in `S::owo` help: consider specifying the generic argument | LL | (S {}).owo(None::<&_>) @@ -11,4 +19,4 @@ LL | (S {}).owo(None::<&_>) error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr index 7a1e850d157fe..52baa213302c0 100644 --- a/tests/ui/inference/question-mark-type-infer.stderr +++ b/tests/ui/inference/question-mark-type-infer.stderr @@ -1,9 +1,12 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/question-mark-type-infer.rs:10:21 | LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect` | + = note: cannot satisfy `_: FromIterator>` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL help: consider specifying the generic argument | LL | l.iter().map(f).collect::>()? @@ -11,4 +14,4 @@ LL | l.iter().map(f).collect::>()? error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inline-const/promotion.rs b/tests/ui/inline-const/promotion.rs new file mode 100644 index 0000000000000..242959c6b5164 --- /dev/null +++ b/tests/ui/inline-const/promotion.rs @@ -0,0 +1,22 @@ +#![feature(inline_const)] +#![allow(arithmetic_overflow, unconditional_panic)] + +// The only way to have promoteds that fail is in `const fn` called from `const`/`static`. +// Make sure that in a `const` block, we do not promote such calls. +const fn div_by_zero() -> i32 { + 1 / 0 +} + +const fn mk_false() -> bool { + false +} + +fn main() { + let v = const { + if mk_false() { + let _x: &'static i32 = &div_by_zero(); + //~^ ERROR: temporary value dropped while borrowed + } + 42 + }; +} diff --git a/tests/ui/inline-const/promotion.stderr b/tests/ui/inline-const/promotion.stderr new file mode 100644 index 0000000000000..795fc8f5921a9 --- /dev/null +++ b/tests/ui/inline-const/promotion.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:17:37 + | +LL | let _x: &'static i32 = &div_by_zero(); + | ------------ ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index bbbb2a86a22da..97e658617cf03 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -5,7 +5,8 @@ LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `u8` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i8` @@ -15,7 +16,8 @@ LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i8` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `u32` @@ -25,7 +27,8 @@ LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `u32` = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i32` @@ -35,7 +38,8 @@ LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u8` @@ -45,7 +49,8 @@ LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i8` @@ -55,7 +60,8 @@ LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i8` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u32` @@ -65,7 +71,8 @@ LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `u32` = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i32` @@ -75,7 +82,8 @@ LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[u8]` to implement `Index` error: aborting due to 8 previous errors diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index d4507a27aeaa1..ecd08e3cdfd29 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -4,7 +4,7 @@ error: this argument must be a function item LL | const_eval_select((), || {}, || {}); | ^^^^^ | - = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:27: 7:29] + = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:27: 7:29} = help: consult the documentation on `const_eval_select` for more information error: this argument must be a function item @@ -13,7 +13,7 @@ error: this argument must be a function item LL | const_eval_select((), || {}, || {}); | ^^^^^ | - = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:34: 7:36] + = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:34: 7:36} = help: consult the documentation on `const_eval_select` for more information error: this argument must be a function item diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs new file mode 100644 index 0000000000000..ffaa4d771d99b --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs @@ -0,0 +1,6 @@ +#[rustc_safe_intrinsic] +//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe +//~| ERROR attribute should be applied to intrinsic functions +fn safe() {} + +fn main() {} diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr new file mode 100644 index 0000000000000..8aeb56598ec1c --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr @@ -0,0 +1,20 @@ +error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: attribute should be applied to intrinsic functions + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn safe() {} + | ------------ not an intrinsic function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index b99bb39d062ce..6f9df64417e8e 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -1,7 +1,7 @@ // run-pass // ignore-wasm32-bare seems not important to test here -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] mod rusti { extern "rust-intrinsic" { @@ -16,6 +16,7 @@ mod rusti { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "macos", diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.stderr b/tests/ui/invalid_dispatch_from_dyn_impls.stderr index b5b32d2f0bd36..168ed37d0e69f 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/tests/ui/invalid_dispatch_from_dyn_impls.stderr @@ -1,37 +1,47 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | -LL | impl DispatchFromDyn> for WrapperWithExtraField - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl DispatchFromDyn> for WrapperWithExtraField +LL | | where +LL | | T: DispatchFromDyn, + | |__________________________^ | = note: extra field `1` of type `i32` is not allowed error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions --> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1 | -LL | impl DispatchFromDyn> for MultiplePointers - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl DispatchFromDyn> for MultiplePointers +LL | | where +LL | | T: Unsize, + | |_________________^ | = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`) -error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1 | LL | impl DispatchFromDyn> for NothingToCoerce {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected a single field to be coerced, none found error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` --> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1 | -LL | impl DispatchFromDyn> for HasReprC - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl DispatchFromDyn> for HasReprC +LL | | where +LL | | T: Unsize, + | |_________________^ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 | -LL | impl DispatchFromDyn> for OverAligned - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl DispatchFromDyn> for OverAligned +LL | | where +LL | | T: Unsize, + | |_____________________^ | = note: extra field `1` of type `OverAlignedZst` is not allowed diff --git a/tests/ui/issues/auxiliary/issue-111011.stderr b/tests/ui/issues/auxiliary/issue-111011.stderr index 082f0f035ad46..c0b48c5842f4a 100644 --- a/tests/ui/issues/auxiliary/issue-111011.stderr +++ b/tests/ui/issues/auxiliary/issue-111011.stderr @@ -17,7 +17,7 @@ LL | bar(async move || {}); | arguments to this function are incorrect | = note: expected struct `Box<(dyn FnOnce() -> _ + 'static)>` - found closure `[closure@$DIR/issue-111011.rs:11:9: 11:22]` + found closure `{closure@$DIR/issue-111011.rs:11:9: 11:22}` = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html note: function defined here --> $DIR/issue-111011.rs:7:4 diff --git a/tests/ui/issues/issue-12127.stderr b/tests/ui/issues/issue-12127.stderr index 2c451b07fbe3a..2e585867941d8 100644 --- a/tests/ui/issues/issue-12127.stderr +++ b/tests/ui/issues/issue-12127.stderr @@ -11,7 +11,7 @@ note: this value implements `FnOnce`, which causes it to be moved when called | LL | f(); | ^ - = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:30]`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `{closure@$DIR/issue-12127.rs:8:24: 8:30}`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr index 806b7f0ac05e9..d2a6a96082e53 100644 --- a/tests/ui/issues/issue-12187-1.stderr +++ b/tests/ui/issues/issue-12187-1.stderr @@ -2,9 +2,9 @@ error[E0282]: type annotations needed for `&T` --> $DIR/issue-12187-1.rs:6:9 | LL | let &v = new(); - | ^^ + | ^^ ----- type must be known at this point | -help: consider giving this pattern a type, where the placeholders `_` are specified +help: consider giving this pattern a type, where the type for type parameter `T` is specified | LL | let &v: &T = new(); | ++++ diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr index a1fa0a2b00245..ac75ebb4256d5 100644 --- a/tests/ui/issues/issue-12187-2.stderr +++ b/tests/ui/issues/issue-12187-2.stderr @@ -2,9 +2,9 @@ error[E0282]: type annotations needed for `&T` --> $DIR/issue-12187-2.rs:6:9 | LL | let &v = new(); - | ^^ + | ^^ ----- type must be known at this point | -help: consider giving this pattern a type, where the placeholders `_` are specified +help: consider giving this pattern a type, where the type for type parameter `T` is specified | LL | let &v: &T = new(); | ++++ diff --git a/tests/ui/issues/issue-16966.stderr b/tests/ui/issues/issue-16966.stderr index 8c92505b5eb28..c53707c5d696a 100644 --- a/tests/ui/issues/issue-16966.stderr +++ b/tests/ui/issues/issue-16966.stderr @@ -1,9 +1,16 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/issue-16966.rs:2:12 | LL | panic!(std::default::Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | -------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | + | | cannot infer type + | required by a bound introduced by this call + | + = note: cannot satisfy `_: Any` +note: required by a bound in `begin_panic` + --> $SRC_DIR/std/src/panicking.rs:LL:COL error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr index 5f45a2f844321..3a8f569a3a5c2 100644 --- a/tests/ui/issues/issue-17551.stderr +++ b/tests/ui/issues/issue-17551.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `B` --> $DIR/issue-17551.rs:6:9 | LL | let foo = B(marker::PhantomData); - | ^^^ + | ^^^ ------------------- type must be known at this point | help: consider giving `foo` an explicit type, where the type for type parameter `T` is specified | diff --git a/tests/ui/issues/issue-22638.rs b/tests/ui/issues/issue-22638.rs index 198ceccc2c33c..c2407227c2b9a 100644 --- a/tests/ui/issues/issue-22638.rs +++ b/tests/ui/issues/issue-22638.rs @@ -1,5 +1,5 @@ // build-fail -// normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`" +// normalize-stderr-test: "<\{closure@.+`" -> "$$CLOSURE`" // normalize-stderr-test: ".nll/" -> "/" #![allow(unused)] @@ -54,7 +54,7 @@ impl D { pub fn matches(&self, f: &F) { let &D(ref a) = self; a.matches(f) - //~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure + //~^ ERROR reached the recursion limit while instantiating `A::matches::<{closure } } diff --git a/tests/ui/issues/issue-24036.stderr b/tests/ui/issues/issue-24036.stderr index 0e73a51faed9a..184383b736942 100644 --- a/tests/ui/issues/issue-24036.stderr +++ b/tests/ui/issues/issue-24036.stderr @@ -6,17 +6,18 @@ LL | let mut x = |c| c + 1; LL | x = |c| c + 1; | ^^^^^^^^^ expected closure, found a different closure | - = note: expected closure `[closure@$DIR/issue-24036.rs:2:17: 2:20]` - found closure `[closure@$DIR/issue-24036.rs:3:9: 3:12]` + = note: expected closure `{closure@$DIR/issue-24036.rs:2:17: 2:20}` + found closure `{closure@$DIR/issue-24036.rs:3:9: 3:12}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object -error[E0282]: type annotations needed +error[E0284]: type annotations needed --> $DIR/issue-24036.rs:9:15 | LL | 1 => |c| c + 1, - | ^ + | ^ - type must be known at this point | + = note: cannot satisfy `<_ as Add>::Output == _` help: consider giving this closure parameter an explicit type | LL | 1 => |c: /* Type */| c + 1, @@ -24,5 +25,5 @@ LL | 1 => |c: /* Type */| c + 1, error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/issues/issue-24446.stderr b/tests/ui/issues/issue-24446.stderr index 4afb87c482549..72d528f1619a0 100644 --- a/tests/ui/issues/issue-24446.stderr +++ b/tests/ui/issues/issue-24446.stderr @@ -1,19 +1,19 @@ -error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time +error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely --> $DIR/issue-24446.rs:2:17 | LL | static foo: dyn Fn() -> u32 = || -> u32 { - | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely | - = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` + = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)` + = note: shared static variables must have a type that implements `Sync` -error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely +error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time --> $DIR/issue-24446.rs:2:17 | LL | static foo: dyn Fn() -> u32 = || -> u32 { - | ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)` - = note: shared static variables must have a type that implements `Sync` + = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr index 59ef28481d0e6..01532de999e3b 100644 --- a/tests/ui/issues/issue-27042.stderr +++ b/tests/ui/issues/issue-27042.stderr @@ -11,11 +11,18 @@ LL | | while true { break }; // but here we cite the whole loop error[E0308]: mismatched types --> $DIR/issue-27042.rs:6:16 | +LL | let _: i32 = + | - expected because of this assignment +LL | 'a: // in this case, the citation is just the `break`: LL | loop { break }; - | ^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 42` + | ---- ^^^^^ expected `i32`, found `()` + | | + | this loop is expected to be of type `i32` + | +help: give it a value of the expected type + | +LL | loop { break 42 }; + | ++ error[E0308]: mismatched types --> $DIR/issue-27042.rs:8:9 diff --git a/tests/ui/issues/issue-33571.stderr b/tests/ui/issues/issue-33571.stderr index 2a9ba5ba71b8f..819a533ddbe2f 100644 --- a/tests/ui/issues/issue-33571.stderr +++ b/tests/ui/issues/issue-33571.stderr @@ -21,6 +21,7 @@ note: unsafe traits like `Sync` should be implemented explicitly | LL | Sync, | ^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index 9d2c315e4dbca..753942dd1d189 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -19,7 +19,8 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>` + = help: for that trait implementation, expected `(u32, _, _)`, found `()` note: the method call chain might not have had the expected associated types --> $DIR/issue-34334.rs:5:43 | diff --git a/tests/ui/issues/issue-40000.stderr b/tests/ui/issues/issue-40000.stderr index c41fbb9d2ec1d..0737a9610e294 100644 --- a/tests/ui/issues/issue-40000.stderr +++ b/tests/ui/issues/issue-40000.stderr @@ -15,6 +15,7 @@ LL | foo(bar); | = note: expected trait object `dyn for<'a> Fn(&'a i32)` found trait object `dyn Fn(&i32)` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-41880.stderr b/tests/ui/issues/issue-41880.stderr index 00c375f8d2acf..6414e26929a41 100644 --- a/tests/ui/issues/issue-41880.stderr +++ b/tests/ui/issues/issue-41880.stderr @@ -5,7 +5,7 @@ LL | pub struct Iterate { | ------------------------ method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::>()); - | ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>` + | ^^^^ method not found in `Iterate<{integer}, {closure@issue-41880.rs:26:24}>` error: aborting due to previous error diff --git a/tests/ui/issues/issue-43355.stderr b/tests/ui/issues/issue-43355.stderr index 57adc8ad5efc6..9aeca8efe4a66 100644 --- a/tests/ui/issues/issue-43355.stderr +++ b/tests/ui/issues/issue-43355.stderr @@ -2,7 +2,7 @@ error[E0119]: conflicting implementations of trait `Trait1>` for type `A` --> $DIR/issue-43355.rs:13:1 | LL | impl Trait1 for T where T: Trait2 { - | -------------------------- first implementation here + | --------------------------------------------- first implementation here ... LL | impl Trait1> for A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr index 8967f49df02a5..e651e2a68d160 100644 --- a/tests/ui/issues/issue-45801.stderr +++ b/tests/ui/issues/issue-45801.stderr @@ -5,6 +5,7 @@ LL | req.get_ref::(); | ^^^^^^^ the trait `Plugin` is not implemented for `Params` | = help: the trait `Plugin` is implemented for `Params` + = help: for that trait implementation, expected `Foo`, found `i32` error: aborting due to previous error diff --git a/tests/ui/issues/issue-46101.stderr b/tests/ui/issues/issue-46101.stderr index 40295b8a11530..a0cdd5d5f0532 100644 --- a/tests/ui/issues/issue-46101.stderr +++ b/tests/ui/issues/issue-46101.stderr @@ -9,6 +9,8 @@ error[E0433]: failed to resolve: partially resolved path in a derive macro | LL | #[derive(Foo::Anything)] | ^^^^^^^^^^^^^ partially resolved path in a derive macro + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/issues/issue-47715.rs index b8088c18dadfe..0a770593bc9ce 100644 --- a/tests/ui/issues/issue-47715.rs +++ b/tests/ui/issues/issue-47715.rs @@ -7,22 +7,22 @@ trait Iterable { } struct Container> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types field: T } enum Enum> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types A(T), } union Union + Copy> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types x: T, } type Type> = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types fn main() { } diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr index dadea34b68836..2ded98781c643 100644 --- a/tests/ui/issues/issue-47715.stderr +++ b/tests/ui/issues/issue-47715.stderr @@ -1,22 +1,22 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:9:37 | LL | struct Container> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:14:30 | LL | enum Enum> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:19:32 | LL | union Union + Copy> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:24:30 | LL | type Type> = T; diff --git a/tests/ui/issues/issue-48838.stderr b/tests/ui/issues/issue-48838.stderr index 3502af7028baa..159199a7fcecc 100644 --- a/tests/ui/issues/issue-48838.stderr +++ b/tests/ui/issues/issue-48838.stderr @@ -5,7 +5,7 @@ LL | Square = |x| x, | ^^^^^ expected `isize`, found closure | = note: expected type `isize` - found closure `[closure@$DIR/issue-48838.rs:2:14: 2:17]` + found closure `{closure@$DIR/issue-48838.rs:2:14: 2:17}` error: aborting due to previous error diff --git a/tests/ui/issues/issue-50600.stderr b/tests/ui/issues/issue-50600.stderr index 7fea7e5c0985e..d285c3467ab4c 100644 --- a/tests/ui/issues/issue-50600.stderr +++ b/tests/ui/issues/issue-50600.stderr @@ -5,7 +5,7 @@ LL | fn([u8; |x: u8| {}]), | ^^^^^^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/issue-50600.rs:2:13: 2:20]` + found closure `{closure@$DIR/issue-50600.rs:2:13: 2:20}` error: aborting due to previous error diff --git a/tests/ui/issues/issue-50688.stderr b/tests/ui/issues/issue-50688.stderr index 6973ad271b40d..df7603d797478 100644 --- a/tests/ui/issues/issue-50688.stderr +++ b/tests/ui/issues/issue-50688.stderr @@ -5,7 +5,7 @@ LL | [1; || {}]; | ^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/issue-50688.rs:2:9: 2:11]` + found closure `{closure@$DIR/issue-50688.rs:2:9: 2:11}` error: aborting due to previous error diff --git a/tests/ui/issues/issue-50714-1.stderr b/tests/ui/issues/issue-50714-1.stderr index 28469bee01714..bacd09b2ae11c 100644 --- a/tests/ui/issues/issue-50714-1.stderr +++ b/tests/ui/issues/issue-50714-1.stderr @@ -1,8 +1,8 @@ -error[E0647]: start function is not allowed to have a `where` clause +error[E0647]: `#[start]` function is not allowed to have a `where` clause --> $DIR/issue-50714-1.rs:9:50 | LL | fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { - | ^^^^^^^^^^^^^^^^^ start function cannot have a `where` clause + | ^^^^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause error: aborting due to previous error diff --git a/tests/ui/issues/issue-51154.stderr b/tests/ui/issues/issue-51154.stderr index d8a833a86f511..002d5ccdc67a0 100644 --- a/tests/ui/issues/issue-51154.stderr +++ b/tests/ui/issues/issue-51154.stderr @@ -9,7 +9,7 @@ LL | let _: Box = Box::new(|| ()); | arguments to this function are incorrect | = note: expected type parameter `F` - found closure `[closure@$DIR/issue-51154.rs:2:30: 2:32]` + found closure `{closure@$DIR/issue-51154.rs:2:30: 2:32}` = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F` note: associated function defined here --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/issues/issue-53251.stderr b/tests/ui/issues/issue-53251.stderr index d5f14e8deb90a..05ea631158964 100644 --- a/tests/ui/issues/issue-53251.stderr +++ b/tests/ui/issues/issue-53251.stderr @@ -32,6 +32,7 @@ note: associated function defined here, with 0 generic parameters | LL | fn f() {} | ^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr index d9a960ce19730..cec8117702a9b 100644 --- a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr +++ b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:2:5 | LL | fn first() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | second == 1 | ^^^^^^^^^^^ expected `()`, found `bool` @@ -44,7 +44,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:8:5 | LL | fn second() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | first == 1 | ^^^^^^^^^^ expected `()`, found `bool` @@ -69,7 +69,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:14:5 | LL | fn bar() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | bar == 1 | ^^^^^^^^ expected `()`, found `bool` diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr index 22b1da64cb315..128288e28f5ac 100644 --- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -5,7 +5,8 @@ LL | let x2: Vec = x1.into_iter().collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `f64`, found `&f64` note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 | @@ -25,7 +26,8 @@ LL | let x3 = x1.into_iter().collect::>(); | required by a bound introduced by this call | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `f64`, found `&f64` note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 | diff --git a/tests/ui/issues/issue-77919.stderr b/tests/ui/issues/issue-77919.stderr index d6dcc8997b9ab..dbbe70ff06990 100644 --- a/tests/ui/issues/issue-77919.stderr +++ b/tests/ui/issues/issue-77919.stderr @@ -27,7 +27,7 @@ LL | const VAL: T; | ------------ `VAL` from trait ... LL | impl TypeVal for Multiply where N: TypeVal {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-9575.stderr b/tests/ui/issues/issue-9575.stderr index 5b8ce84a07168..e49eac3babf8c 100644 --- a/tests/ui/issues/issue-9575.stderr +++ b/tests/ui/issues/issue-9575.stderr @@ -4,8 +4,8 @@ error[E0308]: `#[start]` function has wrong type LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn(isize, *const *const u8) -> _` - found fn pointer `fn(isize, *const *const u8, *const u8) -> _` + = note: expected signature `fn(isize, *const *const u8) -> _` + found signature `fn(isize, *const *const u8, *const u8) -> _` error: aborting due to previous error diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr index 07dc561f06a69..45685ef0ce9cd 100644 --- a/tests/ui/iterators/collect-into-slice.stderr +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -1,3 +1,13 @@ +error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size + --> $DIR/collect-into-slice.rs:6:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/collect-into-slice.rs:6:9 | @@ -18,16 +28,6 @@ LL | let some_generated_vec = (0..10).collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size - --> $DIR/collect-into-slice.rs:6:38 - | -LL | let some_generated_vec = (0..10).collect(); - | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` - | - = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` -note: required by a bound in `collect` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere --> $DIR/collect-into-slice.rs:18:38 | diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index b355da5cb768e..2601c9c0d69d3 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -5,7 +5,8 @@ LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&X>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `X`, found `&X` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:4:26 | @@ -159,7 +160,8 @@ LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `i32`, found `()` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:44:15 | diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr index cc6e1f59c7789..077004ae76163 100644 --- a/tests/ui/kindck/kindck-nonsendable-1.stderr +++ b/tests/ui/kindck/kindck-nonsendable-1.stderr @@ -5,10 +5,10 @@ LL | bar(move|| foo(x)); | --- ------^^^^^^^ | | | | | `Rc` cannot be sent between threads safely - | | within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]` + | | within this `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}` | required by a bound introduced by this call | - = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`, the trait `Send` is not implemented for `Rc` + = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc` note: required because it's used within this closure --> $DIR/kindck-nonsendable-1.rs:9:9 | diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr index 65c99a93c7511..66d4397a2935a 100644 --- a/tests/ui/lang-items/start_lang_item_args.argc.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr @@ -1,8 +1,12 @@ -error: parameter 2 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:75:38 | LL | fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ^^ help: change the type from `i8` to `isize` + | ^^ expected `isize`, found `i8` + | + = note: expected signature `fn(fn() -> _, isize, _, _) -> _` + found signature `fn(fn() -> _, i8, _, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr index f0947a9b3e933..53d776cd846a4 100644 --- a/tests/ui/lang-items/start_lang_item_args.argv.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr @@ -1,8 +1,12 @@ -error: parameter 3 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:89:52 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { - | ^^ help: change the type from `u8` to `*const *const u8` + | ^^ expected `*const *const u8`, found `u8` + | + = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _` + found signature `fn(fn() -> _, _, u8, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr index 08efd5088f99b..7d002e090b5a8 100644 --- a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr @@ -1,13 +1,12 @@ -error: parameter 3 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:82:52 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ expected `u8`, found `usize` | -help: change the type from `*const *const usize` to `*const *const u8` - | -LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ~~~~~~~~~~~~~~~~ + = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _` + found signature `fn(fn() -> _, _, *const *const usize, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr index c20a744661d49..91994b9d74296 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr @@ -1,13 +1,12 @@ -error: parameter 1 of the `start` lang item is incorrect - --> $DIR/start_lang_item_args.rs:61:20 +error[E0308]: lang item `start` function has wrong type + --> $DIR/start_lang_item_args.rs:61:1 | LL | fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | -help: change the type from `fn(i32) -> T` to `fn() -> T` - | -LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ~~~~~~~~~ + = note: expected signature `fn(fn() -> _, _, _, _) -> _` + found signature `fn(fn(i32) -> _, _, _, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr index 8f967252f49be..4582b69850cf7 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -1,13 +1,14 @@ -error: parameter 1 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:68:20 | LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ^^^^^^^^^^^ + | - ^^^^^^^^^^^ expected type parameter `T`, found `u16` + | | + | this type parameter | -help: change the type from `fn() -> u16` to `fn() -> T` - | -LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ~~~~~~~~~ + = note: expected signature `fn(fn() -> T, _, _, _) -> _` + found signature `fn(fn() -> u16, _, _, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr index deb37b868ea89..87940d05e785f 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr @@ -1,8 +1,12 @@ -error: parameter 1 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:54:20 | LL | fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - | ^^^ help: change the type from `u64` to `fn() -> T` + | ^^^ expected fn pointer, found `u64` + | + = note: expected signature `fn(fn() -> T, _, _, _) -> _` + found signature `fn(u64, _, _, _) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr index 004c2a67f62f1..5363871e20223 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr @@ -1,11 +1,12 @@ -error: incorrect number of parameters for the `start` lang item +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:15:1 | LL | fn start() -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: the `start` lang item should have four parameters, but found 0 - = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` + found signature `fn() -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr index 1d8285b59000a..14bfcc3d04d9c 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr @@ -1,8 +1,12 @@ -error: the return type of the `start` lang item is incorrect - --> $DIR/start_lang_item_args.rs:29:84 +error[E0308]: lang item `start` function has wrong type + --> $DIR/start_lang_item_args.rs:29:83 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} - | ^ help: change the type from `()` to `isize` + | ^ expected `isize`, found `()` + | + = note: expected signature `fn(fn() -> _, _, _, _) -> isize` + found signature `fn(fn() -> _, _, _, _)` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr index e545a750f24a9..f873f7614bdce 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr @@ -1,11 +1,12 @@ -error: incorrect number of parameters for the `start` lang item +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:22:1 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: the `start` lang item should have four parameters, but found 3 - = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` + found signature `fn(fn() -> T, isize, *const *const u8) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.rs b/tests/ui/lang-items/start_lang_item_args.rs index 0dbfba39cb605..4a0302bcb1528 100644 --- a/tests/ui/lang-items/start_lang_item_args.rs +++ b/tests/ui/lang-items/start_lang_item_args.rs @@ -13,33 +13,33 @@ pub trait Sized {} #[cfg(missing_all_args)] #[lang = "start"] fn start() -> isize { - //[missing_all_args]~^ ERROR incorrect number of parameters + //[missing_all_args]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(missing_sigpipe_arg)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { - //[missing_sigpipe_arg]~^ ERROR incorrect number of parameters + //[missing_sigpipe_arg]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(missing_ret)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} -//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect +//[missing_ret]~^ ERROR lang item `start` function has wrong type [E0308] #[cfg(start_ret)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { - //[start_ret]~^ ERROR the return type of the `start` lang item is incorrect + //[start_ret]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(too_many_args)] #[lang = "start"] fn start( - //[too_many_args]~^ ERROR incorrect number of parameters + //[too_many_args]~^ ERROR lang item `start` function has wrong type [E0308] _main: fn() -> T, _argc: isize, _argv: *const *const u8, @@ -52,49 +52,49 @@ fn start( #[cfg(main_ty)] #[lang = "start"] fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - //[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect + //[main_ty]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(main_args)] #[lang = "start"] fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - //[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect + //[main_args]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(main_ret)] #[lang = "start"] fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - //[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect + //[main_ret]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(argc)] #[lang = "start"] fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { - //[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect + //[argc]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(argv_inner_ptr)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { - //[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect + //[argv_inner_ptr]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(argv)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { - //[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect + //[argv]~^ ERROR lang item `start` function has wrong type [E0308] 100 } #[cfg(sigpipe)] #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { - //[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect + //[sigpipe]~^ ERROR lang item `start` function has wrong type [E0308] 100 } diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr index b20ae31280133..280d423bd7e1b 100644 --- a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr +++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr @@ -1,8 +1,12 @@ -error: parameter 4 of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:96:80 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { - | ^^^ help: change the type from `i64` to `u8` + | ^^^ expected `u8`, found `i64` + | + = note: expected signature `fn(fn() -> _, _, _, u8) -> _` + found signature `fn(fn() -> _, _, _, i64) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr index 935d5f3c8b426..4e4f8a5cdb39e 100644 --- a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr @@ -1,8 +1,12 @@ -error: the return type of the `start` lang item is incorrect +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:34:87 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { - | ^^ help: change the type from `u8` to `isize` + | ^^ expected `isize`, found `u8` + | + = note: expected signature `fn(fn() -> _, _, _, _) -> isize` + found signature `fn(fn() -> _, _, _, _) -> u8` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr index 30a7ed18a3d23..085d4b1f238e3 100644 --- a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr @@ -1,4 +1,4 @@ -error: incorrect number of parameters for the `start` lang item +error[E0308]: lang item `start` function has wrong type --> $DIR/start_lang_item_args.rs:41:1 | LL | / fn start( @@ -8,10 +8,11 @@ LL | | _argc: isize, ... | LL | | _extra_arg: (), LL | | ) -> isize { - | |__________^ + | |__________^ incorrect number of function parameters | - = note: the `start` lang item should have four parameters, but found 5 - = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` + found signature `fn(fn() -> T, isize, *const *const u8, u8, ()) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.rs b/tests/ui/lang-items/start_lang_item_with_target_feature.rs new file mode 100644 index 0000000000000..3052b7bb56373 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_with_target_feature.rs @@ -0,0 +1,19 @@ +// only-x86_64 +// check-fail + +#![feature(lang_items, no_core, target_feature_11)] +#![no_core] + +#[lang = "copy"] +pub trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[lang = "start"] +#[target_feature(enable = "avx2")] +//~^ ERROR `start` language item function is not allowed to have `#[target_feature]` +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() {} diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr new file mode 100644 index 0000000000000..ff55a1365e458 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr @@ -0,0 +1,11 @@ +error: `start` language item function is not allowed to have `#[target_feature]` + --> $DIR/start_lang_item_with_target_feature.rs:13:1 + | +LL | #[target_feature(enable = "avx2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ------------------------------------------------------------------------------------------- `start` language item function is not allowed to have `#[target_feature]` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 66415f72bcb45..54ecd35ed6acd 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -81,6 +81,7 @@ note: the lifetime requirement is introduced here | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider specifying the type of the closure parameters | LL | let f = |x: &_, y: &_, z: u32| (); diff --git a/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index affb4e8d04434..235092e24634b 100644 --- a/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:19:10 | LL | foo: &'static T - | ^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | struct Foo { | +++++++++ @@ -13,20 +16,24 @@ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 | LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | -- ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | | + | the parameter type `K` must be valid for the lifetime `'a` as defined here... | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | -LL | impl Nested { - | ++++ +LL | fn generic_in_parent<'a, L: X<&'a Nested>>() where K: 'a { + | +++++++++++ error[E0309]: the parameter type `M` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 | LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | -- ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | | + | the parameter type `M` must be valid for the lifetime `'a` as defined here... | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b + 'a>() { | ++++ @@ -35,29 +42,37 @@ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 | LL | fn foo<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | -- ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | | + | the parameter type `K` must be valid for the lifetime `'a` as defined here... | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | -LL | trait X: Sized { - | ++++ +LL | fn foo<'a, L: X<&'a Nested>>() where K: 'a; + | +++++++++++ error[E0309]: the parameter type `Self` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 | LL | fn bar<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | | + | the parameter type `Self` must be valid for the lifetime `'a` as defined here... | - = help: consider adding an explicit lifetime bound `Self: 'a`... - = note: ...so that the reference type `&'a Nested` does not outlive the data it points at +help: consider adding an explicit lifetime bound + | +LL | fn bar<'a, L: X<&'a Nested>>() where Self: 'a; + | ++++++++++++++ error[E0309]: the parameter type `L` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 | LL | fn baz<'a, L, M: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | -- ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | | + | the parameter type `L` must be valid for the lifetime `'a` as defined here... | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn baz<'a, L: 'a, M: X<&'a Nested>>() { | ++++ diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 7049f28e2f6eb..dbc587dd004a4 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue_74400.rs:12:5 | LL | f(data, identity) - | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn g(data: &[T]) { | +++++++++ diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed index f977f0bd3a8c2..7c41549043915 100644 --- a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed @@ -2,7 +2,7 @@ #![allow(warnings)] -fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { +fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { with_restriction::(x) //~ ERROR the parameter type `T` may not live long enough } diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr index 2d58d3a02f35e..79df2c8dfbcc8 100644 --- a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -1,23 +1,15 @@ error[E0311]: the parameter type `T` may not live long enough --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5 | -LL | with_restriction::(x) - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `T` must be valid for the anonymous lifetime defined here... - --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:5:25 - | LL | fn no_restriction(x: &()) -> &() { - | ^^^ -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5 - | + | --- the parameter type `T` must be valid for the anonymous lifetime defined here... LL | with_restriction::(x) - | ^^^^^^^^^^^^^^^^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | -LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { - | +++ ++++ ++ +LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + | +++ ++++ ++ ++ error: aborting due to previous error diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 01ec69a6110fa..92a2ef2f432f1 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -56,7 +56,7 @@ LL | fn d() {} | ^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter --> $DIR/unusual-rib-combinations.rs:29:21 @@ -65,7 +65,7 @@ LL | struct Bar Foo<'a>)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 9 previous errors diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 93716c0b3473f..6b463930b007e 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -25,6 +25,7 @@ note: erroneous constant encountered LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr b/tests/ui/linkage-attr/unstable-flavor.bpf.stderr index 594a461769b36..819da2fb01788 100644 --- a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr +++ b/tests/ui/linkage-attr/unstable-flavor.bpf.stderr @@ -1,2 +1,2 @@ -error: the linker flavor `bpf-linker` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values +error: the linker flavor `bpf` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values diff --git a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr index 714c09df53fee..2ebdc1a903399 100644 --- a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr +++ b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr @@ -1,2 +1,2 @@ -error: the linker flavor `ptx-linker` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values +error: the linker flavor `ptx` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs index b58fd055fdc67..c2c16b28bff10 100644 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ b/tests/ui/linkage-attr/unstable-flavor.rs @@ -3,11 +3,11 @@ // caller). If it passes, all the other unstable options are rejected as well. // // revisions: bpf ptx -// [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf-linker --crate-type=rlib -// [bpf] error-pattern: linker flavor `bpf-linker` is unstable, the `-Z unstable-options` flag +// [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib +// [bpf] error-pattern: linker flavor `bpf` is unstable, the `-Z unstable-options` flag // [bpf] needs-llvm-components: -// [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx-linker --crate-type=rlib -// [ptx] error-pattern: linker flavor `ptx-linker` is unstable, the `-Z unstable-options` flag +// [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib +// [ptx] error-pattern: linker flavor `ptx` is unstable, the `-Z unstable-options` flag // [ptx] needs-llvm-components: #![feature(no_core)] diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr index 2ee718a8c8e11..5084b4a40013a 100644 --- a/tests/ui/lint/cli-unknown-force-warn.stderr +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -6,10 +6,12 @@ warning[E0602]: unknown lint: `foo_qux` warning[E0602]: unknown lint: `foo_qux` | = note: requested on the command line with `--force-warn foo_qux` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning[E0602]: unknown lint: `foo_qux` | = note: requested on the command line with `--force-warn foo_qux` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr index c9a2aff2137a7..65aa196283082 100644 --- a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr @@ -5,6 +5,7 @@ error[E0602]: unknown lint tool: `unknown_tool` error[E0602]: unknown lint tool: `unknown_tool` | = note: requested on the command line with `-A unknown_tool::foo` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/crate_level_only_lint.stderr b/tests/ui/lint/crate_level_only_lint.stderr index 8fb06df2a481a..fbb1ec381c8ff 100644 --- a/tests/ui/lint/crate_level_only_lint.stderr +++ b/tests/ui/lint/crate_level_only_lint.stderr @@ -27,36 +27,48 @@ error: allow(uncommon_codepoints) is ignored unless specified at crate level | LL | #![allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(uncommon_codepoints) is ignored unless specified at crate level --> $DIR/crate_level_only_lint.rs:9:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(uncommon_codepoints) is ignored unless specified at crate level --> $DIR/crate_level_only_lint.rs:17:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(uncommon_codepoints) is ignored unless specified at crate level --> $DIR/crate_level_only_lint.rs:4:10 | LL | #![allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(uncommon_codepoints) is ignored unless specified at crate level --> $DIR/crate_level_only_lint.rs:9:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(uncommon_codepoints) is ignored unless specified at crate level --> $DIR/crate_level_only_lint.rs:17:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 9 previous errors diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr index b2e2bcea1b408..4a2c8fbd68ab1 100644 --- a/tests/ui/lint/forbid-group-group-2.stderr +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -26,6 +26,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -38,6 +39,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -50,6 +52,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -62,6 +65,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -74,6 +78,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -86,6 +91,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -98,6 +104,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: allow(nonstandard_style) incompatible with previous forbid --> $DIR/forbid-group-group-2.rs:7:9 @@ -110,6 +117,7 @@ LL | #[allow(nonstandard_style)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 9 previous errors diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr index 47336d4d890bc..ddaaafa12ec2e 100644 --- a/tests/ui/lint/forbid-group-member.stderr +++ b/tests/ui/lint/forbid-group-member.stderr @@ -22,6 +22,7 @@ LL | #[allow(unused_variables)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: allow(unused_variables) incompatible with previous forbid --> $DIR/forbid-group-member.rs:8:9 @@ -34,6 +35,7 @@ LL | #[allow(unused_variables)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/lint/forbid-member-group.stderr b/tests/ui/lint/forbid-member-group.stderr index e65301778332a..612dccd8d6ca6 100644 --- a/tests/ui/lint/forbid-member-group.stderr +++ b/tests/ui/lint/forbid-member-group.stderr @@ -15,6 +15,8 @@ LL | #![forbid(unused_variables)] LL | LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index 0f58953a54ba8..ecdc625015e4e 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -20,6 +20,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} @@ -33,6 +34,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index 03a32fa6f085f..5f5f2ff52b6d0 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -20,6 +20,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} @@ -33,6 +34,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index b0cd3ddd26f2f..3a0b1201b0cd8 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -21,6 +21,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} @@ -34,6 +35,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index 8c841916c93d4..92555eda2a737 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -21,6 +21,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} @@ -34,6 +35,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index c0144205d6a9b..c14c7957a25f5 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -21,6 +21,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} @@ -34,6 +35,7 @@ LL | pub fn function(_x: Box) {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | pub fn function(_x: Box) {} diff --git a/tests/ui/lint/force-warn/warnings-lint-group.stderr b/tests/ui/lint/force-warn/warnings-lint-group.stderr index 1faeed3370451..3e73269a233ed 100644 --- a/tests/ui/lint/force-warn/warnings-lint-group.stderr +++ b/tests/ui/lint/force-warn/warnings-lint-group.stderr @@ -1,6 +1,8 @@ error[E0602]: `warnings` lint group is not supported with ´--force-warn´ error[E0602]: `warnings` lint group is not supported with ´--force-warn´ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs index 9c8c636812e0d..43ceffb71e509 100644 --- a/tests/ui/lint/invalid_from_utf8.rs +++ b/tests/ui/lint/invalid_from_utf8.rs @@ -1,6 +1,8 @@ // check-pass +#![feature(inline_const)] #![feature(concat_bytes)] + #![warn(invalid_from_utf8_unchecked)] #![warn(invalid_from_utf8)] @@ -90,4 +92,29 @@ pub fn from_utf8() { } } +pub fn from_utf8_with_indirections() { + let mut a = [99, 108, 130, 105, 112, 112, 121]; + std::str::from_utf8_mut(&mut a); + //~^ WARN calls to `std::str::from_utf8_mut` + let mut b = &mut a; + let mut c = b; + std::str::from_utf8_mut(c); + //~^ WARN calls to `std::str::from_utf8_mut` + let mut c = &[99, 108, 130, 105, 112, 112, 121]; + std::str::from_utf8(c); + //~^ WARN calls to `std::str::from_utf8` + const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + std::str::from_utf8(&INVALID_1); + //~^ WARN calls to `std::str::from_utf8` + static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + std::str::from_utf8(&INVALID_2); + //~^ WARN calls to `std::str::from_utf8` + const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; + std::str::from_utf8(INVALID_3); + //~^ WARN calls to `std::str::from_utf8` + const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; + std::str::from_utf8(INVALID_4); + //~^ WARN calls to `std::str::from_utf8` +} + fn main() {} diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr index 8e00d3bf872f4..884165d4f123c 100644 --- a/tests/ui/lint/invalid_from_utf8.stderr +++ b/tests/ui/lint/invalid_from_utf8.stderr @@ -1,43 +1,43 @@ warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:19:9 + --> $DIR/invalid_from_utf8.rs:21:9 | LL | std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes | note: the lint level is defined here - --> $DIR/invalid_from_utf8.rs:4:9 + --> $DIR/invalid_from_utf8.rs:6:9 | LL | #![warn(invalid_from_utf8_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:21:9 + --> $DIR/invalid_from_utf8.rs:23:9 | LL | std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:39:9 + --> $DIR/invalid_from_utf8.rs:41:9 | LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:41:9 + --> $DIR/invalid_from_utf8.rs:43:9 | LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:43:9 + --> $DIR/invalid_from_utf8.rs:45:9 | LL | std::str::from_utf8_unchecked(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^ @@ -45,7 +45,7 @@ LL | std::str::from_utf8_unchecked(b"cl\x82ippy"); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:45:9 + --> $DIR/invalid_from_utf8.rs:47:9 | LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^ @@ -53,45 +53,45 @@ LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:62:9 + --> $DIR/invalid_from_utf8.rs:64:9 | LL | std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); - | ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes | note: the lint level is defined here - --> $DIR/invalid_from_utf8.rs:5:9 + --> $DIR/invalid_from_utf8.rs:7:9 | LL | #![warn(invalid_from_utf8)] | ^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:64:9 + --> $DIR/invalid_from_utf8.rs:66:9 | LL | std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); - | ^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:82:9 + --> $DIR/invalid_from_utf8.rs:84:9 | LL | std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); - | ^^^^^^^^^^^^^^^^^^^^-----------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:84:9 + --> $DIR/invalid_from_utf8.rs:86:9 | LL | std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); - | ^^^^^^^^^^^^^^^^^^^^----------------------------------------------^ - | | - | the literal was valid UTF-8 up to the 2 bytes + | ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:86:9 + --> $DIR/invalid_from_utf8.rs:88:9 | LL | std::str::from_utf8(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^-------------^ @@ -99,12 +99,69 @@ LL | std::str::from_utf8(b"cl\x82ippy"); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:88:9 + --> $DIR/invalid_from_utf8.rs:90:9 | LL | std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^---------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: 12 warnings emitted +warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:97:5 + | +LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8_mut(&mut a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:101:5 + | +LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | std::str::from_utf8_mut(c); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:104:5 + | +LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8(c); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:107:5 + | +LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8(&INVALID_1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:110:5 + | +LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8(&INVALID_2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:113:5 + | +LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8(INVALID_3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with a invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:116:5 + | +LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | std::str::from_utf8(INVALID_4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 19 warnings emitted diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr index 73e27ffda7fee..7a65881b5eda5 100644 --- a/tests/ui/lint/issue-80988.stderr +++ b/tests/ui/lint/issue-80988.stderr @@ -22,6 +22,7 @@ LL | #[deny(warnings)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: deny(warnings) incompatible with previous forbid --> $DIR/issue-80988.rs:7:8 @@ -34,6 +35,7 @@ LL | #[deny(warnings)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/async-await/large_moves.rs b/tests/ui/lint/large_assignments/box_rc_arc_allowed.rs similarity index 57% rename from tests/ui/async-await/large_moves.rs rename to tests/ui/lint/large_assignments/box_rc_arc_allowed.rs index 62b1210469410..33113642023a2 100644 --- a/tests/ui/async-await/large_moves.rs +++ b/tests/ui/lint/large_assignments/box_rc_arc_allowed.rs @@ -1,10 +1,8 @@ #![deny(large_assignments)] #![feature(large_assignments)] -#![cfg_attr(attribute, move_size_limit = "1000")] +#![move_size_limit = "1000"] // build-fail // only-x86_64 -// revisions: attribute option -// [option]compile-flags: -Zmove-size-limit=1000 // edition:2018 // compile-flags: -Zmir-opt-level=0 @@ -12,25 +10,12 @@ use std::{sync::Arc, rc::Rc}; fn main() { - let x = async { - let y = [0; 9999]; - dbg!(y); - thing(&y).await; - dbg!(y); - }; - let z = (x, 42); //~ ERROR large_assignments - let a = z.0; //~ ERROR large_assignments - let b = z.1; let _ = Arc::new([0; 9999]); // OK! let _ = Box::new([0; 9999]); // OK! let _ = Rc::new([0; 9999]); // OK! let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments } -async fn thing(y: &[u8]) { - dbg!(y); -} - struct NotBox { data: [u8; 9999], } diff --git a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr new file mode 100644 index 0000000000000..b45cbe5da4dca --- /dev/null +++ b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr @@ -0,0 +1,23 @@ +error: moving 9999 bytes + --> $DIR/box_rc_arc_allowed.rs:16:13 + | +LL | let _ = NotBox::new([0; 9999]); + | ^^^^^^^^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/box_rc_arc_allowed.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 9999 bytes + --> $DIR/box_rc_arc_allowed.rs:26:13 + | +LL | data, + | ^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/large_assignments/large_future.attribute.stderr b/tests/ui/lint/large_assignments/large_future.attribute.stderr new file mode 100644 index 0000000000000..734b7ff7ba22f --- /dev/null +++ b/tests/ui/lint/large_assignments/large_future.attribute.stderr @@ -0,0 +1,23 @@ +error: moving 10024 bytes + --> $DIR/large_future.rs:19:14 + | +LL | let z = (x, 42); + | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/large_future.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 10024 bytes + --> $DIR/large_future.rs:20:13 + | +LL | let a = z.0; + | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/large_assignments/large_future.option.stderr b/tests/ui/lint/large_assignments/large_future.option.stderr new file mode 100644 index 0000000000000..734b7ff7ba22f --- /dev/null +++ b/tests/ui/lint/large_assignments/large_future.option.stderr @@ -0,0 +1,23 @@ +error: moving 10024 bytes + --> $DIR/large_future.rs:19:14 + | +LL | let z = (x, 42); + | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/large_future.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 10024 bytes + --> $DIR/large_future.rs:20:13 + | +LL | let a = z.0; + | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/large_assignments/large_future.rs b/tests/ui/lint/large_assignments/large_future.rs new file mode 100644 index 0000000000000..834746fa97e71 --- /dev/null +++ b/tests/ui/lint/large_assignments/large_future.rs @@ -0,0 +1,26 @@ +#![deny(large_assignments)] +#![cfg_attr(attribute, feature(large_assignments))] +#![cfg_attr(attribute, move_size_limit = "1000")] +// build-fail +// only-x86_64 +// revisions: attribute option +// [option]compile-flags: -Zmove-size-limit=1000 + +// edition:2018 +// compile-flags: -Zmir-opt-level=0 + +fn main() { + let x = async { + let y = [0; 9999]; + dbg!(y); + thing(&y).await; + dbg!(y); + }; + let z = (x, 42); //~ ERROR large_assignments + let a = z.0; //~ ERROR large_assignments + let b = z.1; +} + +async fn thing(y: &[u8]) { + dbg!(y); +} diff --git a/tests/ui/lint/lint-forbid-attr.stderr b/tests/ui/lint/lint-forbid-attr.stderr index 5977b9c949d50..bd476a0e362d9 100644 --- a/tests/ui/lint/lint-forbid-attr.stderr +++ b/tests/ui/lint/lint-forbid-attr.stderr @@ -15,6 +15,8 @@ LL | #![forbid(deprecated)] LL | LL | #[allow(deprecated)] | ^^^^^^^^^^ overruled by previous forbid + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/lint-forbid-cmdline.stderr b/tests/ui/lint/lint-forbid-cmdline.stderr index 0a92e58c04aa5..ed49a2cb4274a 100644 --- a/tests/ui/lint/lint-forbid-cmdline.stderr +++ b/tests/ui/lint/lint-forbid-cmdline.stderr @@ -13,6 +13,7 @@ LL | #[allow(deprecated)] | ^^^^^^^^^^ overruled by previous forbid | = note: `forbid` lint level was set on command line + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 91b4e509b269e..2c9f045de71f5 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -9,6 +9,8 @@ error[E0452]: malformed lint attribute input | LL | #![allow(bar = "baz")] | ^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: malformed `deny` attribute input --> $DIR/lint-malformed.rs:1:1 @@ -21,12 +23,16 @@ error[E0452]: malformed lint attribute input | LL | #![allow(bar = "baz")] | ^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] | ^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 previous errors diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 80c85d01e53c0..3321afa7fcd75 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -6,10 +6,12 @@ error: lint `raw_pointer_derive` has been removed: using derive with raw pointer error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok | = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok | = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` --> $DIR/lint-removed-cmdline-deny.rs:13:17 diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index ebfae34ade92f..6b76ad3b578c7 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -6,10 +6,12 @@ warning: lint `raw_pointer_derive` has been removed: using derive with raw point warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok | = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok | = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` --> $DIR/lint-removed-cmdline.rs:13:17 diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index df22ef60daf13..0e182a4e5dea0 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -8,11 +8,13 @@ error: lint `bare_trait_object` has been renamed to `bare_trait_objects` | = help: use the new name `bare_trait_objects` = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lint `bare_trait_object` has been renamed to `bare_trait_objects` | = help: use the new name `bare_trait_objects` = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` --> $DIR/lint-renamed-cmdline-deny.rs:10:17 diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index a41284003ed64..675443ddedf5d 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -8,11 +8,13 @@ warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` | = help: use the new name `bare_trait_objects` = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` | = help: use the new name `bare_trait_objects` = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` --> $DIR/lint-renamed-cmdline.rs:9:17 diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 19a4649e16804..609fc56a8ae5f 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -639,18 +639,24 @@ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedT | LL | struct S2(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text --> $DIR/lint-stability-deprecated.rs:102:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text --> $DIR/lint-stability-deprecated.rs:102:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 108 warnings emitted diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr index 858527822220a..0efec51abaf6d 100644 --- a/tests/ui/lint/lint-unexported-no-mangle.stderr +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -10,18 +10,22 @@ warning: lint `private_no_mangle_statics` has been removed: no longer a warning, warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported | = note: requested on the command line with `-F private_no_mangle_fns` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported | = note: requested on the command line with `-F private_no_mangle_statics` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported | = note: requested on the command line with `-F private_no_mangle_fns` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported | = note: requested on the command line with `-F private_no_mangle_statics` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: const items should never be `#[no_mangle]` --> $DIR/lint-unexported-no-mangle.rs:9:1 diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr index 677b5edc894b3..f12ce03ddfcef 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr @@ -11,20 +11,24 @@ error[E0602]: unknown lint: `dead_cod` error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0602]: unknown lint: `dead_cod` | = help: did you mean: `dead_code` = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0602]: unknown lint: `dead_cod` | = help: did you mean: `dead_code` = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr index 10db76ac4f16b..f452fc9eb943c 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -11,20 +11,24 @@ warning[E0602]: unknown lint: `dead_cod` warning[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning[E0602]: unknown lint: `dead_cod` | = help: did you mean: `dead_code` = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning[E0602]: unknown lint: `dead_cod` | = help: did you mean: `dead_code` = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 6 warnings emitted diff --git a/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr deleted file mode 100644 index cd3baa857abff..0000000000000 --- a/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: `No` held across a suspend point, but should not be - --> $DIR/dedup.rs:19:9 - | -LL | let no = No {}; - | ^^ -LL | wheeee(&no).await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/dedup.rs:19:9 - | -LL | let no = No {}; - | ^^ -note: the lint level is defined here - --> $DIR/dedup.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr deleted file mode 100644 index aff2f7c32b96d..0000000000000 --- a/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: `No` held across a suspend point, but should not be - --> $DIR/dedup.rs:19:9 - | -LL | let no = No {}; - | ^^ -LL | wheeee(&no).await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/dedup.rs:19:9 - | -LL | let no = No {}; - | ^^ -note: the lint level is defined here - --> $DIR/dedup.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: `No` held across a suspend point, but should not be - --> $DIR/dedup.rs:20:13 - | -LL | wheeee(&no).await; - | ^^ ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/dedup.rs:20:13 - | -LL | wheeee(&no).await; - | ^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/must_not_suspend/dedup.rs b/tests/ui/lint/must_not_suspend/dedup.rs index 96bdb7715b183..867bdf2ec12bf 100644 --- a/tests/ui/lint/must_not_suspend/dedup.rs +++ b/tests/ui/lint/must_not_suspend/dedup.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 #![feature(must_not_suspend)] #![deny(must_not_suspend)] @@ -16,8 +13,9 @@ async fn wheeee(t: T) { } async fn yes() { - let no = No {}; //~ ERROR `No` held across - wheeee(&no).await; //[no_drop_tracking]~ ERROR `No` held across + let no = No {}; + //~^ ERROR `No` held across + wheeee(&no).await; drop(no); } diff --git a/tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/dedup.stderr similarity index 86% rename from tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr rename to tests/ui/lint/must_not_suspend/dedup.stderr index cd3baa857abff..5d5b04a5d9593 100644 --- a/tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr +++ b/tests/ui/lint/must_not_suspend/dedup.stderr @@ -1,18 +1,19 @@ error: `No` held across a suspend point, but should not be - --> $DIR/dedup.rs:19:9 + --> $DIR/dedup.rs:16:9 | LL | let no = No {}; | ^^ +LL | LL | wheeee(&no).await; | ----- the value is held across this suspend point | help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/dedup.rs:19:9 + --> $DIR/dedup.rs:16:9 | LL | let no = No {}; | ^^ note: the lint level is defined here - --> $DIR/dedup.rs:6:9 + --> $DIR/dedup.rs:3:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr index 64de1ebeaabe7..f0d2117d42b5c 100644 --- a/tests/ui/lint/must_not_suspend/gated.stderr +++ b/tests/ui/lint/must_not_suspend/gated.stderr @@ -18,6 +18,7 @@ LL | #![deny(must_not_suspend)] = note: the `must_not_suspend` lint is unstable = note: see issue #83310 for more information = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `must_not_suspend` --> $DIR/gated.rs:4:1 @@ -28,6 +29,7 @@ LL | #![deny(must_not_suspend)] = note: the `must_not_suspend` lint is unstable = note: see issue #83310 for more information = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs b/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs deleted file mode 100644 index 1bc4a38125753..0000000000000 --- a/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs +++ /dev/null @@ -1,30 +0,0 @@ -// edition:2018 -// compile-flags: -Zdrop-tracking -#![feature(must_not_suspend)] -#![deny(must_not_suspend)] - -#[must_not_suspend = "You gotta use Umm's, ya know?"] -struct Umm { - i: i64 -} - -struct Bar { - u: Umm, -} - -async fn other() {} - -impl Bar { - async fn uhoh(&mut self) { - let guard = &mut self.u; //~ ERROR `Umm` held across - - other().await; - - *guard = Umm { - i: 2 - } - } -} - -fn main() { -} diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr deleted file mode 100644 index 348880b9c9f31..0000000000000 --- a/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: reference to `Umm` held across a suspend point, but should not be - --> $DIR/ref-drop-tracking.rs:19:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -LL | -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/ref-drop-tracking.rs:19:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/ref-drop-tracking.rs:19:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -note: the lint level is defined here - --> $DIR/ref-drop-tracking.rs:4:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr deleted file mode 100644 index fb18c2be9cb3a..0000000000000 --- a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: reference to `Umm` held across a suspend point, but should not be - --> $DIR/ref.rs:22:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -LL | -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/ref.rs:22:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/ref.rs:22:13 - | -LL | let guard = &mut self.u; - | ^^^^^ -note: the lint level is defined here - --> $DIR/ref.rs:7:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr deleted file mode 100644 index 6976dd3499194..0000000000000 --- a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: `Umm` held across a suspend point, but should not be - --> $DIR/ref.rs:22:26 - | -LL | let guard = &mut self.u; - | ^^^^^^ -LL | -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/ref.rs:22:26 - | -LL | let guard = &mut self.u; - | ^^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/ref.rs:22:26 - | -LL | let guard = &mut self.u; - | ^^^^^^ -note: the lint level is defined here - --> $DIR/ref.rs:7:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/ref.rs b/tests/ui/lint/must_not_suspend/ref.rs index d05dcb83ac57c..3b6ef39c9fe0d 100644 --- a/tests/ui/lint/must_not_suspend/ref.rs +++ b/tests/ui/lint/must_not_suspend/ref.rs @@ -1,8 +1,4 @@ // edition:2018 -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir - #![feature(must_not_suspend)] #![deny(must_not_suspend)] @@ -23,7 +19,6 @@ impl Bar { other().await; - let _g = &*guard; *guard = Umm { i: 2 } } } diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/ref.stderr similarity index 87% rename from tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr rename to tests/ui/lint/must_not_suspend/ref.stderr index fb18c2be9cb3a..ed91a4a0bc624 100644 --- a/tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr +++ b/tests/ui/lint/must_not_suspend/ref.stderr @@ -1,5 +1,5 @@ error: reference to `Umm` held across a suspend point, but should not be - --> $DIR/ref.rs:22:13 + --> $DIR/ref.rs:18:13 | LL | let guard = &mut self.u; | ^^^^^ @@ -8,17 +8,17 @@ LL | other().await; | ----- the value is held across this suspend point | note: You gotta use Umm's, ya know? - --> $DIR/ref.rs:22:13 + --> $DIR/ref.rs:18:13 | LL | let guard = &mut self.u; | ^^^^^ help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/ref.rs:22:13 + --> $DIR/ref.rs:18:13 | LL | let guard = &mut self.u; | ^^^^^ note: the lint level is defined here - --> $DIR/ref.rs:7:9 + --> $DIR/ref.rs:3:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr deleted file mode 100644 index 8c8ad1f3788da..0000000000000 --- a/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error: implementer of `Wow` held across a suspend point, but should not be - --> $DIR/trait.rs:24:9 - | -LL | let _guard1 = r#impl(); - | ^^^^^^^ -... -LL | other().await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:24:9 - | -LL | let _guard1 = r#impl(); - | ^^^^^^^ -note: the lint level is defined here - --> $DIR/trait.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: boxed `Wow` trait object held across a suspend point, but should not be - --> $DIR/trait.rs:25:9 - | -LL | let _guard2 = r#dyn(); - | ^^^^^^^ -LL | -LL | other().await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:25:9 - | -LL | let _guard2 = r#dyn(); - | ^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr deleted file mode 100644 index 8c8ad1f3788da..0000000000000 --- a/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error: implementer of `Wow` held across a suspend point, but should not be - --> $DIR/trait.rs:24:9 - | -LL | let _guard1 = r#impl(); - | ^^^^^^^ -... -LL | other().await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:24:9 - | -LL | let _guard1 = r#impl(); - | ^^^^^^^ -note: the lint level is defined here - --> $DIR/trait.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: boxed `Wow` trait object held across a suspend point, but should not be - --> $DIR/trait.rs:25:9 - | -LL | let _guard2 = r#dyn(); - | ^^^^^^^ -LL | -LL | other().await; - | ----- the value is held across this suspend point - | -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:25:9 - | -LL | let _guard2 = r#dyn(); - | ^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/must_not_suspend/trait.rs b/tests/ui/lint/must_not_suspend/trait.rs index cc3ae298dbba7..6c911cb4b0f09 100644 --- a/tests/ui/lint/must_not_suspend/trait.rs +++ b/tests/ui/lint/must_not_suspend/trait.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 #![feature(must_not_suspend)] #![deny(must_not_suspend)] @@ -25,9 +22,6 @@ pub async fn uhoh() { let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across other().await; - - drop(_guard1); - drop(_guard2); } fn main() { diff --git a/tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/trait.stderr similarity index 88% rename from tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr rename to tests/ui/lint/must_not_suspend/trait.stderr index 8c8ad1f3788da..2c03f8e822dfd 100644 --- a/tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr +++ b/tests/ui/lint/must_not_suspend/trait.stderr @@ -1,5 +1,5 @@ error: implementer of `Wow` held across a suspend point, but should not be - --> $DIR/trait.rs:24:9 + --> $DIR/trait.rs:21:9 | LL | let _guard1 = r#impl(); | ^^^^^^^ @@ -8,18 +8,18 @@ LL | other().await; | ----- the value is held across this suspend point | help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:24:9 + --> $DIR/trait.rs:21:9 | LL | let _guard1 = r#impl(); | ^^^^^^^ note: the lint level is defined here - --> $DIR/trait.rs:6:9 + --> $DIR/trait.rs:3:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ error: boxed `Wow` trait object held across a suspend point, but should not be - --> $DIR/trait.rs:25:9 + --> $DIR/trait.rs:22:9 | LL | let _guard2 = r#dyn(); | ^^^^^^^ @@ -28,7 +28,7 @@ LL | other().await; | ----- the value is held across this suspend point | help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/trait.rs:25:9 + --> $DIR/trait.rs:22:9 | LL | let _guard2 = r#dyn(); | ^^^^^^^ diff --git a/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr deleted file mode 100644 index e24cffdd0df43..0000000000000 --- a/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: `Umm` held across a suspend point, but should not be - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -note: the lint level is defined here - --> $DIR/unit.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr deleted file mode 100644 index e24cffdd0df43..0000000000000 --- a/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: `Umm` held across a suspend point, but should not be - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/unit.rs:22:9 - | -LL | let _guard = bar(); - | ^^^^^^ -note: the lint level is defined here - --> $DIR/unit.rs:6:9 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/lint/must_not_suspend/unit.rs b/tests/ui/lint/must_not_suspend/unit.rs index fbc51b366817c..af4a76caa4e11 100644 --- a/tests/ui/lint/must_not_suspend/unit.rs +++ b/tests/ui/lint/must_not_suspend/unit.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 #![feature(must_not_suspend)] #![deny(must_not_suspend)] @@ -10,6 +7,7 @@ struct Umm { i: i64 } + fn bar() -> Umm { Umm { i: 1 diff --git a/tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/unit.stderr similarity index 86% rename from tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr rename to tests/ui/lint/must_not_suspend/unit.stderr index e24cffdd0df43..11c95c1464ae1 100644 --- a/tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr +++ b/tests/ui/lint/must_not_suspend/unit.stderr @@ -1,5 +1,5 @@ error: `Umm` held across a suspend point, but should not be - --> $DIR/unit.rs:22:9 + --> $DIR/unit.rs:20:9 | LL | let _guard = bar(); | ^^^^^^ @@ -7,17 +7,17 @@ LL | other().await; | ----- the value is held across this suspend point | note: You gotta use Umm's, ya know? - --> $DIR/unit.rs:22:9 + --> $DIR/unit.rs:20:9 | LL | let _guard = bar(); | ^^^^^^ help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/unit.rs:22:9 + --> $DIR/unit.rs:20:9 | LL | let _guard = bar(); | ^^^^^^ note: the lint level is defined here - --> $DIR/unit.rs:6:9 + --> $DIR/unit.rs:3:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr deleted file mode 100644 index 4f7b40a5efed1..0000000000000 --- a/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr +++ /dev/null @@ -1,26 +0,0 @@ -warning: `Umm` held across a suspend point, but should not be - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -note: the lint level is defined here - --> $DIR/warn.rs:7:9 - | -LL | #![warn(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -warning: 1 warning emitted - diff --git a/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr deleted file mode 100644 index 4f7b40a5efed1..0000000000000 --- a/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr +++ /dev/null @@ -1,26 +0,0 @@ -warning: `Umm` held across a suspend point, but should not be - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -LL | other().await; - | ----- the value is held across this suspend point - | -note: You gotta use Umm's, ya know? - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/warn.rs:24:9 - | -LL | let _guard = bar(); - | ^^^^^^ -note: the lint level is defined here - --> $DIR/warn.rs:7:9 - | -LL | #![warn(must_not_suspend)] - | ^^^^^^^^^^^^^^^^ - -warning: 1 warning emitted - diff --git a/tests/ui/lint/must_not_suspend/warn.rs b/tests/ui/lint/must_not_suspend/warn.rs index 5a4863169ea35..2d5dd01e5bffb 100644 --- a/tests/ui/lint/must_not_suspend/warn.rs +++ b/tests/ui/lint/must_not_suspend/warn.rs @@ -1,6 +1,3 @@ -// revisions: no_drop_tracking drop_tracking drop_tracking_mir -// [drop_tracking] compile-flags: -Zdrop-tracking -// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir // edition:2018 // run-pass #![feature(must_not_suspend)] @@ -21,9 +18,9 @@ fn bar() -> Umm { async fn other() {} pub async fn uhoh() { - let _guard = bar(); //~ WARNING `Umm` held across + let guard = bar(); //~ WARNING `Umm` held across other().await; - drop(_guard); + drop(guard); } fn main() { diff --git a/tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/warn.stderr similarity index 64% rename from tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr rename to tests/ui/lint/must_not_suspend/warn.stderr index 4f7b40a5efed1..e59656e508c01 100644 --- a/tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr +++ b/tests/ui/lint/must_not_suspend/warn.stderr @@ -1,23 +1,23 @@ warning: `Umm` held across a suspend point, but should not be - --> $DIR/warn.rs:24:9 + --> $DIR/warn.rs:21:9 | -LL | let _guard = bar(); - | ^^^^^^ +LL | let guard = bar(); + | ^^^^^ LL | other().await; | ----- the value is held across this suspend point | note: You gotta use Umm's, ya know? - --> $DIR/warn.rs:24:9 + --> $DIR/warn.rs:21:9 | -LL | let _guard = bar(); - | ^^^^^^ +LL | let guard = bar(); + | ^^^^^ help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/warn.rs:24:9 + --> $DIR/warn.rs:21:9 | -LL | let _guard = bar(); - | ^^^^^^ +LL | let guard = bar(); + | ^^^^^ note: the lint level is defined here - --> $DIR/warn.rs:7:9 + --> $DIR/warn.rs:4:9 | LL | #![warn(must_not_suspend)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/noop-method-call.fixed b/tests/ui/lint/noop-method-call.fixed index eeb80279fd816..4d9834f7df625 100644 --- a/tests/ui/lint/noop-method-call.fixed +++ b/tests/ui/lint/noop-method-call.fixed @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![feature(rustc_attrs)] #![allow(unused)] use std::borrow::Borrow; @@ -49,3 +50,15 @@ fn non_generic(non_clone_type: &PlainType) { non_clone_type; //~^ WARN call to `.clone()` on a reference in this situation does nothing } + +struct DiagnosticClone; +impl Clone for DiagnosticClone { + #[rustc_diagnostic_item = "other_clone"] + fn clone(&self) -> Self { + DiagnosticClone + } +} + +fn with_other_diagnostic_item(x: DiagnosticClone) { + x.clone(); +} diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index 9569a0dfc617e..6242a00e03348 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![feature(rustc_attrs)] #![allow(unused)] use std::borrow::Borrow; @@ -49,3 +50,15 @@ fn non_generic(non_clone_type: &PlainType) { non_clone_type.clone(); //~^ WARN call to `.clone()` on a reference in this situation does nothing } + +struct DiagnosticClone; +impl Clone for DiagnosticClone { + #[rustc_diagnostic_item = "other_clone"] + fn clone(&self) -> Self { + DiagnosticClone + } +} + +fn with_other_diagnostic_item(x: DiagnosticClone) { + x.clone(); +} diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index aefc2706fd529..d04f44022eefd 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -1,5 +1,5 @@ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:15:25 + --> $DIR/noop-method-call.rs:16:25 | LL | let _ = &mut encoded.clone(); | ^^^^^^^^ help: remove this redundant call @@ -8,7 +8,7 @@ LL | let _ = &mut encoded.clone(); = note: `#[warn(noop_method_call)]` on by default warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:17:21 + --> $DIR/noop-method-call.rs:18:21 | LL | let _ = &encoded.clone(); | ^^^^^^^^ help: remove this redundant call @@ -16,7 +16,7 @@ LL | let _ = &encoded.clone(); = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:23:71 + --> $DIR/noop-method-call.rs:24:71 | LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); | ^^^^^^^^ help: remove this redundant call @@ -24,7 +24,7 @@ LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clon = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:31:63 + --> $DIR/noop-method-call.rs:32:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ help: remove this redundant call @@ -32,7 +32,7 @@ LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); = note: the type `PlainType` does not implement `Deref`, so calling `deref` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.borrow()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:35:66 + --> $DIR/noop-method-call.rs:36:66 | LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); | ^^^^^^^^^ help: remove this redundant call @@ -40,7 +40,7 @@ LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); = note: the type `PlainType` does not implement `Borrow`, so calling `borrow` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:44:19 + --> $DIR/noop-method-call.rs:45:19 | LL | non_clone_type.clone(); | ^^^^^^^^ help: remove this redundant call @@ -48,7 +48,7 @@ LL | non_clone_type.clone(); = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:49:19 + --> $DIR/noop-method-call.rs:50:19 | LL | non_clone_type.clone(); | ^^^^^^^^ help: remove this redundant call diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index cd693ae166cde..7b286eb1d18e5 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -1,51 +1,27 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + #![feature(lint_reasons)] #![warn(absolute_paths_not_starting_with_crate, reason = 0)] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE reason must be a string literal //~| NOTE reason must be a string literal #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE reason must be a string literal //~| NOTE reason must be a string literal #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument //~| NOTE bad attribute argument #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument //~| NOTE bad attribute argument #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument -//~| NOTE bad attribute argument //~| NOTE bad attribute argument #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] //~^ ERROR malformed lint attribute -//~| ERROR malformed lint attribute -//~| NOTE reason in lint attribute must come last //~| NOTE reason in lint attribute must come last #![warn(missing_copy_implementations, reason)] //~^ WARN unknown lint diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index 5521af17c8412..003da5673704f 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -1,5 +1,5 @@ error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:3:58 + --> $DIR/reasons-erroneous.rs:5:58 | LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ reason must be a string literal @@ -11,121 +11,43 @@ LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condem | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:13:29 + --> $DIR/reasons-erroneous.rs:11:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:13:29 - | -LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:22:23 - | -LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:22:23 - | -LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:31:36 - | -LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:31:36 - | -LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:40:44 - | -LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] - | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:45:25 - | -LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:3:58 - | -LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] - | ^ reason must be a string literal - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:8:40 - | -LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:13:29 - | -LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:13:29 - | -LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:22:23 - | -LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:22:23 + --> $DIR/reasons-erroneous.rs:14:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:31:36 - | -LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument - -error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:31:36 + --> $DIR/reasons-erroneous.rs:17:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:40:44 + --> $DIR/reasons-erroneous.rs:20:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:45:25 + --> $DIR/reasons-erroneous.rs:23:25 | LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last warning: unknown lint: `reason` - --> $DIR/reasons-erroneous.rs:50:39 + --> $DIR/reasons-erroneous.rs:26:39 | LL | #![warn(missing_copy_implementations, reason)] | ^^^^^^ | = note: `#[warn(unknown_lints)]` on by default -error: aborting due to 20 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 7745d4ef4c3a2..25e0c75f70db2 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -36,6 +36,8 @@ unsafe fn ref_to_mut() { //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::mem::transmute::<_, *mut i32>(num); //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::cell::UnsafeCell::raw_get( //~^ ERROR casting `&T` to `&mut T` is undefined behavior num as *const i32 as *const std::cell::UnsafeCell @@ -47,8 +49,24 @@ unsafe fn ref_to_mut() { let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; let _num = &mut *deferred; //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let deferred_rebind = deferred; + let _num = &mut *deferred_rebind; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const _ as usize as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + static NUM: &'static i32 = &2; + let num = NUM as *const i32 as *mut i32; + let num = num; + let num = num; + let _num = &mut *num; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + let cell = &std::cell::UnsafeCell::new(0); + let _num = &mut *(cell as *const _ as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior unsafe fn generic_ref_cast_mut(this: &T) -> &mut T { &mut *((this as *const _) as *mut _) @@ -85,15 +103,22 @@ unsafe fn assign_to_ref() { //~^ ERROR assigning to `&T` is undefined behavior *std::mem::transmute::<_, *mut i32>(num) += 1; //~^ ERROR assigning to `&T` is undefined behavior + *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1; + //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write( //~^ ERROR assigning to `&T` is undefined behavior std::mem::transmute::<*const i32, *mut i32>(num), -1i32, ); + *((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5; + //~^ ERROR assigning to `&T` is undefined behavior let value = num as *const i32 as *mut i32; *value = 1; //~^ ERROR assigning to `&T` is undefined behavior + let value_rebind = value; + *value_rebind = 1; + //~^ ERROR assigning to `&T` is undefined behavior *(num as *const i32).cast::().cast_mut() = 2; //~^ ERROR assigning to `&T` is undefined behavior *(num as *const _ as usize as *mut i32) = 2; @@ -111,6 +136,7 @@ unsafe fn assign_to_ref() { } } +const RAW_PTR: *mut u8 = 1 as *mut u8; unsafe fn no_warn() { let num = &3i32; let mut_num = &mut 3i32; @@ -125,6 +151,11 @@ unsafe fn no_warn() { let mut value = 3; let value: *const i32 = &mut value; *(value as *const i16 as *mut i16) = 42; + *RAW_PTR = 42; // RAW_PTR is defined outside the function body, + // make sure we don't ICE on it when trying to + // determine if we should lint on it or not. + let cell = &std::cell::UnsafeCell::new(0); + let _num = &mut *(cell.get() as *mut i32); fn safe_as_mut(x: &std::cell::UnsafeCell) -> &mut T { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 1189942c809dd..8d5f8da6852b5 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -82,6 +82,14 @@ LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(num); error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:39:16 | +LL | let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:41:16 + | LL | let _num = &mut *std::cell::UnsafeCell::raw_get( | ________________^ LL | | @@ -92,7 +100,7 @@ LL | | ); = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:45:16 + --> $DIR/reference_casting.rs:47:16 | LL | let deferred = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -102,7 +110,7 @@ LL | let _num = &mut *deferred; = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:48:16 + --> $DIR/reference_casting.rs:50:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; | ---------------------------------------------------------------------------- casting happend here @@ -112,7 +120,18 @@ LL | let _num = &mut *deferred; = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:50:16 + --> $DIR/reference_casting.rs:53:16 + | +LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; + | ---------------------------------------------------------------------------- casting happend here +... +LL | let _num = &mut *deferred_rebind; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:55:16 | LL | let _num = &mut *(num as *const _ as usize as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +139,35 @@ LL | let _num = &mut *(num as *const _ as usize as *mut i32); = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:54:9 + --> $DIR/reference_casting.rs:57:16 + | +LL | let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:64:16 + | +LL | let num = NUM as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | let _num = &mut *num; + | ^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:68:16 + | +LL | let _num = &mut *(cell as *const _ as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get` + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:72:9 | LL | &mut *((this as *const _) as *mut _) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,7 +175,7 @@ LL | &mut *((this as *const _) as *mut _) = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:59:18 + --> $DIR/reference_casting.rs:77:18 | LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +183,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:64:18 + --> $DIR/reference_casting.rs:82:18 | LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +191,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:74:5 + --> $DIR/reference_casting.rs:92:5 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -152,7 +199,7 @@ LL | *(a as *const _ as *mut _) = String::from("Replaced"); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:76:5 + --> $DIR/reference_casting.rs:94:5 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +207,7 @@ LL | *(a as *const _ as *mut String) += " world"; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:78:5 + --> $DIR/reference_casting.rs:96:5 | LL | *std::ptr::from_ref(num).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,7 +215,7 @@ LL | *std::ptr::from_ref(num).cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:80:5 + --> $DIR/reference_casting.rs:98:5 | LL | *std::ptr::from_ref({ num }).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +223,7 @@ LL | *std::ptr::from_ref({ num }).cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:82:5 + --> $DIR/reference_casting.rs:100:5 | LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +231,7 @@ LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:84:5 + --> $DIR/reference_casting.rs:102:5 | LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,7 +239,7 @@ LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:86:5 + --> $DIR/reference_casting.rs:104:5 | LL | *std::mem::transmute::<_, *mut i32>(num) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +247,15 @@ LL | *std::mem::transmute::<_, *mut i32>(num) += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:88:5 + --> $DIR/reference_casting.rs:106:5 + | +LL | *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:108:5 | LL | / std::ptr::write( LL | | @@ -212,7 +267,16 @@ LL | | ); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:95:5 + --> $DIR/reference_casting.rs:113:5 + | +LL | *((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get` + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:117:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -222,7 +286,18 @@ LL | *value = 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:97:5 + --> $DIR/reference_casting.rs:120:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | *value_rebind = 1; + | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:122:5 | LL | *(num as *const i32).cast::().cast_mut() = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,7 +305,7 @@ LL | *(num as *const i32).cast::().cast_mut() = 2; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:99:5 + --> $DIR/reference_casting.rs:124:5 | LL | *(num as *const _ as usize as *mut i32) = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +313,7 @@ LL | *(num as *const _ as usize as *mut i32) = 2; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:101:5 + --> $DIR/reference_casting.rs:126:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -249,7 +324,7 @@ LL | std::ptr::write(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:103:5 + --> $DIR/reference_casting.rs:128:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -260,7 +335,7 @@ LL | std::ptr::write_unaligned(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:105:5 + --> $DIR/reference_casting.rs:130:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -271,12 +346,12 @@ LL | std::ptr::write_volatile(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:109:9 + --> $DIR/reference_casting.rs:134:9 | LL | *(this as *const _ as *mut _) = a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, visit -error: aborting due to 32 previous errors +error: aborting due to 40 previous errors diff --git a/tests/ui/lint/register-tool-lint.stderr b/tests/ui/lint/register-tool-lint.stderr index 842d845ff7c33..7ebdbdec92972 100644 --- a/tests/ui/lint/register-tool-lint.stderr +++ b/tests/ui/lint/register-tool-lint.stderr @@ -13,6 +13,7 @@ LL | #![warn(abc::my_lint)] | ^^^ | = help: add `#![register_tool(abc)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs new file mode 100644 index 0000000000000..1e2ff12a20624 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs @@ -0,0 +1,30 @@ +// check-pass +// incremental + +#![feature(lint_reasons)] +#![warn(unused)] + +struct OneUnused; +struct TwoUnused; + +impl OneUnused { + #[expect(unused)] + fn unused() {} +} + +impl TwoUnused { + #[expect(unused)] + fn unused1(){} + + // This unused method has `#[expect(unused)]`, so the compiler should not emit a warning. + // This ui test was added after a regression in the compiler where it did not recognize multiple + // `#[expect(unused)]` annotations inside of impl blocks. + // issue 114416 + #[expect(unused)] + fn unused2(){} +} + +fn main() { + let _ = OneUnused; + let _ = TwoUnused; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs index 479ee198e1743..77cb5e88bf713 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs @@ -1,24 +1,20 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + #![feature(lint_reasons)] #[forbid(unused_variables)] //~^ NOTE `forbid` level set here -//~| NOTE `forbid` level set here #[expect(unused_variables)] //~^ ERROR incompatible with previous forbid [E0453] //~| NOTE overruled by previous forbid -//~| ERROR incompatible with previous forbid [E0453] -//~| NOTE overruled by previous forbid fn expect_forbidden_lint_1() {} #[forbid(while_true)] //~^ NOTE `forbid` level set here -//~| NOTE `forbid` level set here //~| NOTE the lint level is defined here #[expect(while_true)] //~^ ERROR incompatible with previous forbid [E0453] //~| NOTE overruled by previous forbid -//~| ERROR incompatible with previous forbid [E0453] -//~| NOTE overruled by previous forbid fn expect_forbidden_lint_2() { // This while loop will produce a `while_true` lint as the lint level // at this node is still `forbid` and the `while_true` check happens diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr index a8116e93404f2..0f42ffbdea36b 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr @@ -1,32 +1,14 @@ error[E0453]: expect(unused_variables) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:6:10 + --> $DIR/expect_with_forbid.rs:7:10 | LL | #[forbid(unused_variables)] | ---------------- `forbid` level set here -... -LL | #[expect(unused_variables)] - | ^^^^^^^^^^^^^^^^ overruled by previous forbid - -error[E0453]: expect(while_true) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:17:10 - | -LL | #[forbid(while_true)] - | ---------- `forbid` level set here -... -LL | #[expect(while_true)] - | ^^^^^^^^^^ overruled by previous forbid - -error[E0453]: expect(unused_variables) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:6:10 - | -LL | #[forbid(unused_variables)] - | ---------------- `forbid` level set here -... +LL | LL | #[expect(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid error[E0453]: expect(while_true) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:17:10 + --> $DIR/expect_with_forbid.rs:15:10 | LL | #[forbid(while_true)] | ---------- `forbid` level set here @@ -35,17 +17,17 @@ LL | #[expect(while_true)] | ^^^^^^^^^^ overruled by previous forbid error: denote infinite loops with `loop { ... }` - --> $DIR/expect_with_forbid.rs:26:5 + --> $DIR/expect_with_forbid.rs:22:5 | LL | while true {} | ^^^^^^^^^^ help: use `loop` | note: the lint level is defined here - --> $DIR/expect_with_forbid.rs:13:10 + --> $DIR/expect_with_forbid.rs:12:10 | LL | #[forbid(while_true)] | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/trivial_casts.stderr b/tests/ui/lint/trivial_casts.stderr index 74f962835c255..5e2115574585b 100644 --- a/tests/ui/lint/trivial_casts.stderr +++ b/tests/ui/lint/trivial_casts.stderr @@ -128,7 +128,7 @@ LL | let _ = &baz as &dyn Fn(i32); | = help: cast can be replaced by coercion; this might require a temporary variable -error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:22]` as `&dyn Fn(i32)` +error: trivial cast: `&{closure@$DIR/trivial_casts.rs:72:13: 72:22}` as `&dyn Fn(i32)` --> $DIR/trivial_casts.rs:73:13 | LL | let _ = &x as &dyn Fn(i32); diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs index 0c9c79c08b251..3f6dab35475e8 100644 --- a/tests/ui/lint/unaligned_references.rs +++ b/tests/ui/lint/unaligned_references.rs @@ -1,3 +1,6 @@ +use std::mem::ManuallyDrop; +use std::fmt::Debug; + #[repr(packed)] pub struct Good { data: u64, @@ -27,6 +30,26 @@ impl Foo for Packed2 { } } +// Test for #115396 +fn packed_dyn() { + #[repr(packed)] + struct Unaligned(ManuallyDrop); + + let ref local = Unaligned(ManuallyDrop::new([3, 5, 8u64])); + let foo: &Unaligned = &*local; + println!("{:?}", &*foo.0); //~ ERROR reference to packed field + let foo: &Unaligned<[u64]> = &*local; + println!("{:?}", &*foo.0); //~ ERROR reference to packed field + + // Even if the actual alignment is 1, we cannot know that when looking at `dyn Debug.` + let ref local = Unaligned(ManuallyDrop::new([3, 5, 8u8])); + let foo: &Unaligned = &*local; + println!("{:?}", &*foo.0); //~ ERROR reference to packed field + // However, we *can* know the alignment when looking at a slice. + let foo: &Unaligned<[u8]> = &*local; + println!("{:?}", &*foo.0); // no error! +} + fn main() { unsafe { let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.stderr index d3abc37669f59..328cafbd9864b 100644 --- a/tests/ui/lint/unaligned_references.stderr +++ b/tests/ui/lint/unaligned_references.stderr @@ -1,5 +1,5 @@ error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:25:13 + --> $DIR/unaligned_references.rs:28:13 | LL | &self.x; | ^^^^^^^ @@ -9,7 +9,37 @@ LL | &self.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:34:17 + --> $DIR/unaligned_references.rs:40:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:42:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:47:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:57:17 | LL | let _ = &good.ptr; | ^^^^^^^^^ @@ -19,7 +49,7 @@ LL | let _ = &good.ptr; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:35:17 + --> $DIR/unaligned_references.rs:58:17 | LL | let _ = &good.data; | ^^^^^^^^^^ @@ -29,7 +59,7 @@ LL | let _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:37:17 + --> $DIR/unaligned_references.rs:60:17 | LL | let _ = &good.data as *const _; | ^^^^^^^^^^ @@ -39,7 +69,7 @@ LL | let _ = &good.data as *const _; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:38:27 + --> $DIR/unaligned_references.rs:61:27 | LL | let _: *const _ = &good.data; | ^^^^^^^^^^ @@ -49,7 +79,7 @@ LL | let _: *const _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:40:17 + --> $DIR/unaligned_references.rs:63:17 | LL | let _ = good.data.clone(); | ^^^^^^^^^ @@ -59,7 +89,7 @@ LL | let _ = good.data.clone(); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:42:17 + --> $DIR/unaligned_references.rs:65:17 | LL | let _ = &good.data2[0]; | ^^^^^^^^^^^^^^ @@ -69,7 +99,7 @@ LL | let _ = &good.data2[0]; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:51:17 + --> $DIR/unaligned_references.rs:74:17 | LL | let _ = &packed2.x; | ^^^^^^^^^^ @@ -79,7 +109,7 @@ LL | let _ = &packed2.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:90:20 + --> $DIR/unaligned_references.rs:113:20 | LL | let _ref = &m1.1.a; | ^^^^^^^ @@ -89,7 +119,7 @@ LL | let _ref = &m1.1.a; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:93:20 + --> $DIR/unaligned_references.rs:116:20 | LL | let _ref = &m2.1.a; | ^^^^^^^ @@ -98,6 +128,6 @@ LL | let _ref = &m2.1.a; = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) -error: aborting due to 10 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/loops/loop-break-value.rs b/tests/ui/loops/loop-break-value.rs index 51c9a36a03956..c35200520cb5d 100644 --- a/tests/ui/loops/loop-break-value.rs +++ b/tests/ui/loops/loop-break-value.rs @@ -95,4 +95,67 @@ fn main() { break LOOP; //~^ ERROR cannot find value `LOOP` in this scope } + + let _ = 'a: loop { + loop { + break; // This doesn't affect the expected break type of the 'a loop + loop { + loop { + break 'a 1; + } + } + } + break; //~ ERROR mismatched types + }; + + let _ = 'a: loop { + loop { + break; // This doesn't affect the expected break type of the 'a loop + loop { + loop { + break 'a 1; + } + } + } + break 'a; //~ ERROR mismatched types + }; + + loop { + break; + let _ = loop { + break 2; + loop { + break; + } + }; + break 2; //~ ERROR mismatched types + } + + 'a: loop { + break; + let _ = 'a: loop { + //~^ WARNING label name `'a` shadows a label name that is already in scope + break 2; + loop { + break 'a; //~ ERROR mismatched types + } + }; + break 2; //~ ERROR mismatched types + } + + 'a: loop { + break; + let _ = 'a: loop { + //~^ WARNING label name `'a` shadows a label name that is already in scope + break 'a 2; + loop { + break 'a; //~ ERROR mismatched types + } + }; + break 2; //~ ERROR mismatched types + }; + + loop { // point at the return type + break 2; //~ ERROR mismatched types + } } diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr index 5525dbb9005d3..a691960f96257 100644 --- a/tests/ui/loops/loop-break-value.stderr +++ b/tests/ui/loops/loop-break-value.stderr @@ -1,3 +1,21 @@ +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/loop-break-value.rs:136:17 + | +LL | 'a: loop { + | -- first declared here +LL | break; +LL | let _ = 'a: loop { + | ^^ label `'a` already in scope + +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/loop-break-value.rs:148:17 + | +LL | 'a: loop { + | -- first declared here +LL | break; +LL | let _ = 'a: loop { + | ^^ label `'a` already in scope + error[E0425]: cannot find value `LOOP` in this scope --> $DIR/loop-break-value.rs:95:15 | @@ -134,7 +152,10 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:4:31 | LL | let val: ! = loop { break break; }; - | ^^^^^ expected `!`, found `()` + | --- ---- ^^^^^ expected `!`, found `()` + | | | + | | this loop is expected to be of type `!` + | expected because of this assignment | = note: expected type `!` found unit type `()` @@ -142,24 +163,38 @@ LL | let val: ! = loop { break break; }; error[E0308]: mismatched types --> $DIR/loop-break-value.rs:11:19 | +LL | break "asdf"; + | ------------ expected because of this `break` +LL | } else { LL | break 123; | ^^^ expected `&str`, found integer error[E0308]: mismatched types --> $DIR/loop-break-value.rs:16:15 | +LL | let _: i32 = loop { + | - ---- this loop is expected to be of type `i32` + | | + | expected because of this assignment LL | break "asdf"; | ^^^^^^ expected `i32`, found `&str` error[E0308]: mismatched types --> $DIR/loop-break-value.rs:21:31 | +LL | let _: i32 = 'outer_loop: loop { + | - ---- this loop is expected to be of type `i32` + | | + | expected because of this assignment +LL | loop { LL | break 'outer_loop "nope"; | ^^^^^^ expected `i32`, found `&str` error[E0308]: mismatched types --> $DIR/loop-break-value.rs:73:26 | +LL | break; + | ----- expected because of this `break` LL | break 'c 123; | ^^^ expected `()`, found integer @@ -167,7 +202,11 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:80:15 | LL | break (break, break); - | ^^^^^^^^^^^^^^ expected `()`, found `(!, !)` + | ^-----^^-----^ + | || | + | || expected because of this `break` + | |expected because of this `break` + | expected `()`, found `(!, !)` | = note: expected unit type `()` found tuple `(!, !)` @@ -175,19 +214,119 @@ LL | break (break, break); error[E0308]: mismatched types --> $DIR/loop-break-value.rs:85:15 | +LL | break; + | ----- expected because of this `break` LL | break 2; | ^ expected `()`, found integer error[E0308]: mismatched types --> $DIR/loop-break-value.rs:90:9 | +LL | break 2; + | ------- expected because of this `break` LL | break; - | ^^^^^ - | | - | expected integer, found `()` - | help: give it a value of the expected type: `break value` + | ^^^^^ expected integer, found `()` + | +help: give it a value of the expected type + | +LL | break value; + | +++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:108:9 + | +LL | break 'a 1; + | ---------- expected because of this `break` +... +LL | break; + | ^^^^^ expected integer, found `()` + | +help: give it a value of the expected type + | +LL | break value; + | +++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:120:9 + | +LL | break 'a 1; + | ---------- expected because of this `break` +... +LL | break 'a; + | ^^^^^^^^ expected integer, found `()` + | +help: give it a value of the expected type + | +LL | break 'a value; + | +++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:131:15 + | +LL | break; + | ----- expected because of this `break` +... +LL | break 2; + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:140:17 + | +LL | break 2; + | ------- expected because of this `break` +LL | loop { +LL | break 'a; + | ^^^^^^^^ expected integer, found `()` + | +help: give it a value of the expected type + | +LL | break 'a value; + | +++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:143:15 + | +LL | break; + | ----- expected because of this `break` +... +LL | break 2; + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:152:17 + | +LL | break 'a 2; + | ---------- expected because of this `break` +LL | loop { +LL | break 'a; + | ^^^^^^^^ expected integer, found `()` + | +help: give it a value of the expected type + | +LL | break 'a value; + | +++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:155:15 + | +LL | break; + | ----- expected because of this `break` +... +LL | break 2; + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:159:15 + | +LL | fn main() { + | - expected `()` because of this return type +... +LL | loop { // point at the return type + | ---- this loop is expected to be of type `()` +LL | break 2; + | ^ expected `()`, found integer -error: aborting due to 17 previous errors; 1 warning emitted +error: aborting due to 25 previous errors; 3 warnings emitted Some errors have detailed explanations: E0308, E0425, E0571. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-labeled-break-value.stderr b/tests/ui/loops/loop-labeled-break-value.stderr index aa04d330f25d7..694d6c306f645 100644 --- a/tests/ui/loops/loop-labeled-break-value.stderr +++ b/tests/ui/loops/loop-labeled-break-value.stderr @@ -2,28 +2,43 @@ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:3:29 | LL | let _: i32 = loop { break }; - | ^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 42` + | - ---- ^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment + | +help: give it a value of the expected type + | +LL | let _: i32 = loop { break 42 }; + | ++ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:6:37 | LL | let _: i32 = 'inner: loop { break 'inner }; - | ^^^^^^^^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 'inner 42` + | - ---- ^^^^^^^^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment + | +help: give it a value of the expected type + | +LL | let _: i32 = 'inner: loop { break 'inner 42 }; + | ++ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:9:45 | LL | let _: i32 = 'inner2: loop { loop { break 'inner2 } }; - | ^^^^^^^^^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 'inner2 42` + | - ---- ^^^^^^^^^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment + | +help: give it a value of the expected type + | +LL | let _: i32 = 'inner2: loop { loop { break 'inner2 42 } }; + | ++ error: aborting due to 3 previous errors diff --git a/tests/ui/loops/loop-properly-diverging-2.stderr b/tests/ui/loops/loop-properly-diverging-2.stderr index 5030a2935b9d7..1d1ae60cda174 100644 --- a/tests/ui/loops/loop-properly-diverging-2.stderr +++ b/tests/ui/loops/loop-properly-diverging-2.stderr @@ -2,10 +2,15 @@ error[E0308]: mismatched types --> $DIR/loop-properly-diverging-2.rs:2:23 | LL | let x: i32 = loop { break }; - | ^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 42` + | - ---- ^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment + | +help: give it a value of the expected type + | +LL | let x: i32 = loop { break 42 }; + | ++ error: aborting due to previous error diff --git a/tests/ui/lub-glb/old-lub-glb-object.stderr b/tests/ui/lub-glb/old-lub-glb-object.stderr index 3d0c171e013b3..c476d6f692b7b 100644 --- a/tests/ui/lub-glb/old-lub-glb-object.stderr +++ b/tests/ui/lub-glb/old-lub-glb-object.stderr @@ -15,6 +15,7 @@ LL | _ => y, | = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/macros/builtin-std-paths-fail.stderr b/tests/ui/macros/builtin-std-paths-fail.stderr index 004a39043b778..331943843c02a 100644 --- a/tests/ui/macros/builtin-std-paths-fail.stderr +++ b/tests/ui/macros/builtin-std-paths-fail.stderr @@ -15,12 +15,16 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` | LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` --> $DIR/builtin-std-paths-fail.rs:4:11 | LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0433]: failed to resolve: could not find `bench` in `core` --> $DIR/builtin-std-paths-fail.rs:7:9 @@ -63,12 +67,16 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` | LL | std::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` --> $DIR/builtin-std-paths-fail.rs:16:10 | LL | std::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0433]: failed to resolve: could not find `bench` in `std` --> $DIR/builtin-std-paths-fail.rs:19:8 diff --git a/tests/ui/macros/meta-item-absolute-path.stderr b/tests/ui/macros/meta-item-absolute-path.stderr index c53971e245fdb..f0d763d7abbaa 100644 --- a/tests/ui/macros/meta-item-absolute-path.stderr +++ b/tests/ui/macros/meta-item-absolute-path.stderr @@ -9,6 +9,8 @@ error[E0433]: failed to resolve: maybe a missing crate `Absolute`? | LL | #[derive(::Absolute)] | ^^^^^^^^ maybe a missing crate `Absolute`? + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 816f99baa8495..8b4e6250a3080 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -3,6 +3,7 @@ // compile-flags: --test #![feature(async_closure)] +#![feature(auto_traits)] #![feature(box_patterns)] #![feature(const_trait_impl)] #![feature(decl_macro)] diff --git a/tests/ui/main-wrong-type.stderr b/tests/ui/main-wrong-type.stderr index 43efaf884e3a7..1e5f368758e6a 100644 --- a/tests/ui/main-wrong-type.stderr +++ b/tests/ui/main-wrong-type.stderr @@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type LL | fn main(foo: S) { | ^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn()` - found fn pointer `fn(S)` + = note: expected signature `fn()` + found signature `fn(S)` error: aborting due to previous error diff --git a/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr index e713d1451cfd2..64bccda56c65e 100644 --- a/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr +++ b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/overlapping-impl-1-modulo-regions.rs:14:21 | LL | impl F for T {} - | ^ ...so that the type `T` will meet its required lifetime bounds + | ^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl F for T {} | +++++++++ diff --git a/tests/ui/match/issue-72896.rs b/tests/ui/match/issue-72896-non-partial-eq-const.rs similarity index 78% rename from tests/ui/match/issue-72896.rs rename to tests/ui/match/issue-72896-non-partial-eq-const.rs index 3a8b82037310a..a3095f0be83c1 100644 --- a/tests/ui/match/issue-72896.rs +++ b/tests/ui/match/issue-72896-non-partial-eq-const.rs @@ -17,7 +17,8 @@ const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; fn main() { match CONST_SET { - CONST_SET => { /* ok */ } + CONST_SET => { /* ok */ } //~WARN: must implement `PartialEq` + //~| previously accepted _ => panic!("match fell through?"), } } diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr new file mode 100644 index 0000000000000..a7fc0cfc05457 --- /dev/null +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `EnumSet` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `EnumSet` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index e0f8a5447b081..0a022dc3984f5 100644 --- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec` --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9 | LL | let mut x = Vec::new(); - | ^^^^^ + | ^^^^^ ---------- type must be known at this point | help: consider giving `x` an explicit type, where the type for type parameter `T` is specified | diff --git a/tests/ui/methods/method-missing-call.stderr b/tests/ui/methods/method-missing-call.stderr index 040a65d168091..bc508461b690c 100644 --- a/tests/ui/methods/method-missing-call.stderr +++ b/tests/ui/methods/method-missing-call.stderr @@ -9,7 +9,7 @@ help: use parentheses to call the method LL | .get_x(); | ++ -error[E0615]: attempted to take value of method `filter_map` on type `Filter, [closure@$DIR/method-missing-call.rs:27:20: 27:23]>, [closure@$DIR/method-missing-call.rs:28:23: 28:28]>` +error[E0615]: attempted to take value of method `filter_map` on type `Filter, {closure@$DIR/method-missing-call.rs:27:20: 27:23}>, {closure@$DIR/method-missing-call.rs:28:23: 28:28}>` --> $DIR/method-missing-call.rs:29:16 | LL | .filter_map; diff --git a/tests/ui/mismatched_types/issue-19109.stderr b/tests/ui/mismatched_types/issue-19109.stderr index 5cef64bb16926..ca819d93a50a4 100644 --- a/tests/ui/mismatched_types/issue-19109.stderr +++ b/tests/ui/mismatched_types/issue-19109.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:4:5 | LL | fn function(t: &mut dyn Trait) { - | - help: try adding a return type: `-> *mut dyn Trait` + | - help: try adding a return type: `-> *mut dyn Trait` LL | t as *mut dyn Trait | ^^^^^^^^^^^^^^^^^^^ expected `()`, found `*mut dyn Trait` | diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr index 4d230ce9a7ab5..bac27788a2dc6 100644 --- a/tests/ui/mismatched_types/issue-36053-2.stderr +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -15,7 +15,7 @@ help: consider adjusting the signature so it borrows its argument LL | once::<&str>("str").fuse().filter(|a: &&str| true).count(); | + -error[E0599]: the method `count` exists for struct `Filter>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied +error[E0599]: the method `count` exists for struct `Filter>, {closure@issue-36053-2.rs:7:39}>`, but its trait bounds were not satisfied --> $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); @@ -28,12 +28,12 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); = note: doesn't satisfy `_: Iterator` | = note: the following trait bounds were not satisfied: - `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool` - which is required by `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` - `[closure@$DIR/issue-36053-2.rs:7:39: 7:48]: FnMut<(&&str,)>` - which is required by `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` - `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` - which is required by `&mut Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool` + which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>` + which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + which is required by `&mut Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` error: aborting due to 2 previous errors diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs deleted file mode 100644 index 0ccd441cc6489..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs +++ /dev/null @@ -1,11 +0,0 @@ -// gate-test-packed_bundled_libs - -// ignore-wasm32-bare -// compile-flags: --crate-type rlib -// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -// build-fail - -#[link(name = "rust_test_helpers", kind = "static", modifiers = "+bundle,+whole-archive")] -extern "C" {} - -fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr deleted file mode 100644 index 8a9fed740b04e..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - -error: aborting due to previous error - diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs deleted file mode 100644 index 18d4b52a34c3d..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs +++ /dev/null @@ -1,8 +0,0 @@ -// gate-test-packed_bundled_libs - -// ignore-wasm32-bare -// compile-flags: -l static:+bundle,+whole-archive=rust_test_helpers --crate-type rlib -// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -// build-fail - -fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr deleted file mode 100644 index 8a9fed740b04e..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - -error: aborting due to previous error - diff --git a/tests/ui/native-library-link-flags/modifiers-override.stderr b/tests/ui/native-library-link-flags/modifiers-override.stderr index eb3ab55c31044..64427651e9f62 100644 --- a/tests/ui/native-library-link-flags/modifiers-override.stderr +++ b/tests/ui/native-library-link-flags/modifiers-override.stderr @@ -21,6 +21,8 @@ error: overriding linking modifiers from command line is not supported | LL | extern "C" {} | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr index 5b6f023512332..49f55db1e25cd 100644 --- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!` +error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!` --> $DIR/fallback-closure-wrap.rs:18:31 | LL | let error = Closure::wrap(Box::new(move || { @@ -10,7 +10,7 @@ LL | | }) as Box); | = note: expected unit type `()` found type `!` - = note: required for the cast from `Box<[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]>` to `Box` + = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box` error: aborting due to previous error diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index 99dfce8690343..59292ed68a306 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -33,10 +33,12 @@ error[E0308]: mismatched types --> $DIR/issue-52443.rs:4:17 | LL | [(); loop { break }]; - | ^^^^^ - | | - | expected `usize`, found `()` - | help: give it a value of the expected type: `break 42` + | ^^^^^ expected `usize`, found `()` + | +help: give it a value of the expected type + | +LL | [(); loop { break 42 }]; + | ++ error[E0015]: cannot convert `RangeFrom` into an iterator in constants --> $DIR/issue-52443.rs:9:21 diff --git a/tests/ui/never_type/never-from-impl-is-reserved.stderr b/tests/ui/never_type/never-from-impl-is-reserved.stderr index f9f7c787ecbc3..871c512052821 100644 --- a/tests/ui/never_type/never-from-impl-is-reserved.stderr +++ b/tests/ui/never_type/never-from-impl-is-reserved.stderr @@ -5,7 +5,7 @@ LL | impl MyTrait for MyFoo {} | ---------------------- first implementation here LL | // This will conflict with the first impl if we impl `for T: From`. LL | impl MyTrait for T where T: From {} - | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` | = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index 54c16230fe68b..cb37863058931 100644 --- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -5,6 +5,7 @@ LL | >::from(never); | ^ the trait `From<()>` is not implemented for `E` | = help: the trait `From` is implemented for `E` + = help: for that trait implementation, expected `!`, found `()` error: aborting due to previous error diff --git a/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr index 46dba0064339f..aeb0a1394ccca 100644 --- a/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr +++ b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr @@ -15,6 +15,7 @@ LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; | = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... = note: ...but `Trait` is actually implemented for the type `&'static ()` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index 1e3a5328d3d35..b3cb7813e19c8 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) i32)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index bc4ba93f88499..4f0156728ac1e 100644 --- a/tests/ui/nll/closure-requirements/escape-argument.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index f8383cc42a205..ccf56bf6f37df 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?4 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 113173d8f764c..a16433c9d374b 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index ba15199ab5a11..9e0f16c0fc783 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] = note: number of external vids: 2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index f2bf83c6c59e4..e4989e321550f 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 2734326ed6471..be35e62d0704b 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 5ab321eb666de..8880dd816a1fe 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index 595fd5ff565cb..47774b63f8186 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 62b0e3eed85b5..3404bb128278d 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 6f2044d621eb3..e40648912e3cf 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 1aa7de1e13703..a20f885fe81f4 100644 --- a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -25,10 +25,13 @@ LL | | T: Trait<'a>, error[E0309]: the parameter type `T` may not live long enough --> $DIR/propagate-from-trait-match.rs:43:9 | +LL | fn supply<'a, T>(value: T) + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | require(value); | ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Trait<'a> + 'a, | ++++ diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 7635f2ede0a31..18fb7195d021f 100644 --- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, (), ] diff --git a/tests/ui/nll/issue-54556-stephaneyfx.stderr b/tests/ui/nll/issue-54556-stephaneyfx.stderr index f9e82cb003fc2..0dfea0fd748d4 100644 --- a/tests/ui/nll/issue-54556-stephaneyfx.stderr +++ b/tests/ui/nll/issue-54556-stephaneyfx.stderr @@ -12,7 +12,7 @@ LL | } | - | | | `stmt` dropped here while still borrowed - | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Map, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:19]>` + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Map, {closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:19}>` | = note: the temporary is part of an expression at the end of a block; consider forcing this temporary to be dropped sooner, before the block's local variables are dropped diff --git a/tests/ui/nll/issue-97997.stderr b/tests/ui/nll/issue-97997.stderr index 46440c021f543..89eaf77adf063 100644 --- a/tests/ui/nll/issue-97997.stderr +++ b/tests/ui/nll/issue-97997.stderr @@ -15,6 +15,7 @@ LL | ::ASSOC; | = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr index d8b26f0b0171e..4e741abc2dcf2 100644 --- a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr +++ b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -37,10 +37,12 @@ LL | || { None::<&'a &'b ()>; }; error[E0309]: the parameter type `T` may not live long enough --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10 | +LL | fn test_early_type<'a: 'a, T>() { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | || { None::<&'a T>; }; | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test_early_type<'a: 'a, T: 'a>() { | ++++ @@ -48,10 +50,12 @@ LL | fn test_early_type<'a: 'a, T: 'a>() { error[E0309]: the parameter type `T` may not live long enough --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10 | +LL | fn test_late_type<'a, T>() { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | || { None::<&'a T>; }; | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test_late_type<'a, T: 'a>() { | ++++ diff --git a/tests/ui/nll/issue-98693.stderr b/tests/ui/nll/issue-98693.stderr index 15ca38aa25dce..a3d87d74a8e94 100644 --- a/tests/ui/nll/issue-98693.stderr +++ b/tests/ui/nll/issue-98693.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-98693.rs:16:9 | LL | assert_static::(); - | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test() { | +++++++++ diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr index e0d476a33b23b..cab75e630a7c8 100644 --- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr +++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/min-choice-reject-ambiguous.rs:17:5 | +LL | fn test_b<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c> + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | type_test::<'_, T>() // This should pass if we pick 'b. | ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'b + 'a, | ++++ @@ -12,10 +15,13 @@ LL | T: 'b + 'a, error[E0309]: the parameter type `T` may not live long enough --> $DIR/min-choice-reject-ambiguous.rs:28:5 | +LL | fn test_c<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c> + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | type_test::<'_, T>() // This should pass if we pick 'c. | ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'c + 'a, | ++++ diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index c3dd4257a7366..988eee61027bc 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -38,6 +38,7 @@ LL | accept(callback); | = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types --> $DIR/missing-universe-cause-issue-114907.rs:33:5 @@ -73,6 +74,8 @@ error: higher-ranked subtype error | LL | accept(callback); | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index b945ffedda5ae..804071a3e6f77 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -15,6 +15,7 @@ LL | let _x = ::make_f(); | = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 @@ -24,6 +25,7 @@ LL | let _x = ::make_f(); | = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr b/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr index 64b08a9b32fb3..ff9d750570e59 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/impl-trait-outlives.rs:11:5 | +LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | x | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Debug + 'a, | ++++ @@ -12,10 +15,13 @@ LL | T: Debug + 'a, error[E0309]: the parameter type `T` may not live long enough --> $DIR/impl-trait-outlives.rs:26:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | x | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'b + Debug + 'a, | ++++ diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr index d949e29b2b812..6de023ffdd416 100644 --- a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/projection-implied-bounds.rs:30:36 | LL | twice(value, |value_ref, item| invoke2(value_ref, item)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn generic2(value: T) { | +++++++++ diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr index 433024c30bbcf..4f93fb4eaea34 100644 --- a/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -25,11 +25,16 @@ LL | | T: Iterator, error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-closure.rs:25:31 | +LL | fn no_region<'a, T>(x: Box) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound + | +LL | T: Iterator, ::Item: 'a + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: external requirements --> $DIR/projection-no-regions-closure.rs:34:23 @@ -82,11 +87,16 @@ LL | | T: 'b + Iterator, error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-closure.rs:42:31 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +LL | T: 'b + Iterator, ::Item: 'a + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: external requirements --> $DIR/projection-no-regions-closure.rs:52:23 diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr index e0ff544fe4713..da76ac1c474a3 100644 --- a/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr +++ b/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -1,20 +1,30 @@ error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-fn.rs:13:5 | +LL | fn no_region<'a, T>(mut x: T) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(x.next()) - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound + | +LL | T: Iterator, ::Item: 'a + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-fn.rs:28:5 | +LL | fn wrong_region<'a, 'b, T>(mut x: T) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(x.next()) - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +LL | T: 'b + Iterator, ::Item: 'a + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr index ebdce7bc10832..dda60398198e7 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -27,10 +27,13 @@ LL | | T: Anything<'b>, error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:45:39 | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Anything<'b> + 'a, | ++++ @@ -77,10 +80,13 @@ LL | | 'a: 'a, error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:56:39 | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Anything<'b> + 'a, | ++++ diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index dbad8e478463c..c157e89ff8f31 100644 --- a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -26,11 +26,13 @@ LL | | T: Anything<'b, 'c>, error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:38:39 | +LL | fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) + | -- the associated type `>::AssocType` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the type `>::AssocType` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... - = note: ...so that the type `>::AssocType` will meet its required lifetime bounds note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 @@ -60,11 +62,13 @@ LL | | 'a: 'a, error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 | +LL | fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) + | -- the associated type `>::AssocType` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the type `>::AssocType` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... - = note: ...so that the type `>::AssocType` will meet its required lifetime bounds note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index b4435fe06bccc..1fa74f67ccd71 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -1,11 +1,13 @@ error[E0309]: the associated type `>::Output` may not live long enough --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5 | +LL | fn foo1<'a, 'b, T>() -> &'a () + | -- the associated type `>::Output` must be valid for the lifetime `'a` as defined here... +... LL | bar::() - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the type `>::Output` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `>::Output: 'a`... - = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr index ddeaf3c1f9e8c..c8dbe4ebc6d94 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -1,11 +1,13 @@ error[E0309]: the associated type `>::Output` may not live long enough --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5 | +LL | fn foo1<'a, 'b, T>() -> &'a () + | -- the associated type `>::Output` must be valid for the lifetime `'a` as defined here... +... LL | bar::<>::Output>() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `>::Output` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `>::Output: 'a`... - = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr index 0df44644d6a9c..f78708dc48d94 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-where-clause-none.rs:14:5 | +LL | fn foo<'a, T>() -> &'a () + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | bar::() | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: MyTrait<'a> + 'a, | ++++ diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 660211fe21ad0..59e29e9a420fe 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: late-bound region is '?2 @@ -46,10 +46,12 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31 | +LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn generic_fail<'a, T: 'a>(cell: Cell<&'a ()>, value: T) { | ++++ diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index ddad1d205e761..3468c5ad37298 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -25,10 +25,13 @@ LL | | T: Debug, error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27 | +LL | fn no_region<'a, T>(x: Box) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | with_signature(x, |y| y) | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Debug + 'a, | ++++ @@ -36,10 +39,13 @@ LL | T: Debug + 'a, error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | x | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'b + Debug + 'a, | ++++ diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index bb455e9aed090..cef4a0f1e9377 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -24,10 +24,13 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9 | +LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | require(&x, &y) | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { | ++++ @@ -84,10 +87,13 @@ LL | | T: 'b, error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9 | +LL | fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | require(&x, &y) | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'b + 'a, | ++++ diff --git a/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr index 5fb69255dbade..73f01ff1519a4 100644 --- a/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn-body.rs:17:5 | +LL | fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | outlives(cell, t) | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn region_static<'a, T: 'a>(cell: Cell<&'a usize>, t: T) { | ++++ diff --git a/tests/ui/nll/ty-outlives/ty-param-fn.stderr b/tests/ui/nll/ty-outlives/ty-param-fn.stderr index 825b26d2f777b..56bd41051e276 100644 --- a/tests/ui/nll/ty-outlives/ty-param-fn.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-fn.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn.rs:9:5 | +LL | fn no_region<'a, T>(x: Box) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | x | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: Debug + 'a, | ++++ @@ -12,10 +15,13 @@ LL | T: Debug + 'a, error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn.rs:24:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | x | ^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | T: 'b + Debug + 'a, | ++++ diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr index 0d8480a42c1e2..37098b585dfea 100644 --- a/tests/ui/nll/type-check-pointer-comparisons.stderr +++ b/tests/ui/nll/type-check-pointer-comparisons.stderr @@ -61,6 +61,8 @@ LL | x == y; = help: see for more information about variance help: `'a` and `'b` must be the same: replace one with the other + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough --> $DIR/type-check-pointer-comparisons.rs:16:5 @@ -93,6 +95,8 @@ LL | f == g; = help: see for more information about variance help: `'a` and `'b` must be the same: replace one with the other + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr index 6b0dcb414aea5..dcf049a7a61a0 100644 --- a/tests/ui/nll/user-annotations/normalization-2.stderr +++ b/tests/ui/nll/user-annotations/normalization-2.stderr @@ -131,6 +131,7 @@ help: the following changes may resolve your lifetime errors | = help: replace `'a` with `'static` = help: replace `'b` with `'static` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough --> $DIR/normalization-2.rs:89:5 @@ -185,6 +186,7 @@ help: the following changes may resolve your lifetime errors | = help: replace `'a` with `'static` = help: replace `'b` with `'static` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough --> $DIR/normalization-2.rs:117:5 diff --git a/tests/ui/nll/user-annotations/normalization-infer.stderr b/tests/ui/nll/user-annotations/normalization-infer.stderr index 12854ab6816b7..41d563a55231a 100644 --- a/tests/ui/nll/user-annotations/normalization-infer.stderr +++ b/tests/ui/nll/user-annotations/normalization-infer.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/normalization-infer.rs:11:12 | LL | let _: <(_,) as Tr>::Ty = a; - | ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test1(a: A, b: B, c: C) { | +++++++++ @@ -13,9 +16,12 @@ error[E0310]: the parameter type `B` may not live long enough --> $DIR/normalization-infer.rs:12:5 | LL | Some::<<(_,) as Tr>::Ty>(b); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `B` must be valid for the static lifetime... + | ...so that the type `B` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test1(a: A, b: B, c: C) { | +++++++++ @@ -24,9 +30,12 @@ error[E0310]: the parameter type `C` may not live long enough --> $DIR/normalization-infer.rs:13:11 | LL | || -> <(_,) as Tr>::Ty { c }; - | ^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `C` must be valid for the static lifetime... + | ...so that the type `C` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test1(a: A, b: B, c: C) { | +++++++++ @@ -35,9 +44,12 @@ error[E0310]: the parameter type `D` may not live long enough --> $DIR/normalization-infer.rs:14:6 | LL | |d: <(_,) as Tr>::Ty| -> D { d }; - | ^ ...so that the type `D` will meet its required lifetime bounds + | ^ + | | + | the parameter type `D` must be valid for the static lifetime... + | ...so that the type `D` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test1(a: A, b: B, c: C) { | +++++++++ @@ -46,9 +58,12 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/normalization-infer.rs:28:12 | LL | let _: Alias<_, _> = (a, 0u8); - | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test2(a: A, b: B, c: C) { | +++++++++ @@ -57,9 +72,12 @@ error[E0310]: the parameter type `B` may not live long enough --> $DIR/normalization-infer.rs:29:5 | LL | Some::>((b, 0u8)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `B` must be valid for the static lifetime... + | ...so that the type `B` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test2(a: A, b: B, c: C) { | +++++++++ @@ -68,9 +86,12 @@ error[E0310]: the parameter type `C` may not live long enough --> $DIR/normalization-infer.rs:30:11 | LL | || -> Alias<_, _> { (c, 0u8) }; - | ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `C` must be valid for the static lifetime... + | ...so that the type `C` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test2(a: A, b: B, c: C) { | +++++++++ diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr index 75561f4119aa5..33446e9d16247 100644 --- a/tests/ui/no-send-res-ports.stderr +++ b/tests/ui/no-send-res-ports.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely LL | thread::spawn(move|| { | ------------- ^----- | | | - | _____|_____________within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]` + | _____|_____________within this `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}` | | | | | required by a bound introduced by this call LL | | @@ -13,7 +13,7 @@ LL | | println!("{:?}", y); LL | | }); | |_____^ `Rc<()>` cannot be sent between threads safely | - = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`, the trait `Send` is not implemented for `Rc<()>` + = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>` note: required because it appears within the type `Port<()>` --> $DIR/no-send-res-ports.rs:5:8 | diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr index db9307c61853f..17cf938d170b0 100644 --- a/tests/ui/not-clone-closure.stderr +++ b/tests/ui/not-clone-closure.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` +error[E0277]: the trait bound `S: Clone` is not satisfied in `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` --> $DIR/not-clone-closure.rs:11:23 | LL | let hello = move || { - | ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` + | ------- within this `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` ... LL | let hello = hello.clone(); - | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S` + | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S` | note: required because it's used within this closure --> $DIR/not-clone-closure.rs:7:17 diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr index d0a4179fe3e1c..659679e444095 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -14,6 +14,7 @@ LL | fn foo(_: &dyn Foo) {} | ^^^^^^^^ 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unnecessary associated type bound for not object safe associated type --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 @@ -22,6 +23,7 @@ LL | fn foo(_: &dyn Foo) {} | ^^^^^^^^ 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr index 40429fe756f46..2d2bb27b8f39a 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr @@ -1,17 +1,11 @@ error[E0311]: the parameter type `Self` may not live long enough | -note: the parameter type `Self` must be valid for the lifetime `'a` as defined here... - --> $DIR/object-safety-supertrait-mentions-GAT.rs:9:26 - | -LL | trait SuperTrait: for<'a> GatTrait = T> { - | ^^ - = help: consider adding an explicit lifetime bound `Self: 'a`... - = note: ...so that the type `Self` will meet its required lifetime bounds... note: ...that is required by this bound --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15 | LL | Self: 'a; | ^^ + = help: consider adding an explicit lifetime bound `Self: 'a`... error: associated item referring to unboxed trait object for its own trait --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr index 6133f3263ab64..233d49876436a 100644 --- a/tests/ui/offset-of/offset-of-output-type.stderr +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -42,7 +42,7 @@ error[E0308]: mismatched types --> $DIR/offset-of-output-type.rs:19:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type ... LL | offset_of!(S, v) | ^^^^^^^^^^^^^^^^ expected `()`, found `usize` diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr index a0fad0acd0b5c..36d80f3e681bb 100644 --- a/tests/ui/on-unimplemented/impl-substs.stderr +++ b/tests/ui/on-unimplemented/impl-substs.stderr @@ -7,7 +7,8 @@ LL | Foo::::foo((1i32, 1i32, 1i32)); | required by a bound introduced by this call | = help: the trait `Foo` is not implemented for `(i32, i32, i32)` - = help: the trait `Foo` is implemented for `(A, B, C)` + = help: the trait `Foo` is implemented for `(i32, i32, i32)` + = help: for that trait implementation, expected `i32`, found `usize` error: aborting due to previous error diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr index 2253c5992a64a..3a0b8353fa5eb 100644 --- a/tests/ui/on-unimplemented/on-impl.stderr +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -8,6 +8,7 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is implemented for `[i32]` + = help: for that trait implementation, expected `usize`, found `u32` error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 @@ -17,6 +18,7 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is implemented for `[i32]` + = help: for that trait implementation, expected `usize`, found `u32` error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 @@ -26,6 +28,7 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is implemented for `[i32]` + = help: for that trait implementation, expected `usize`, found `u32` error: aborting due to 3 previous errors diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index b9bca211f438b..5e0117be5295c 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -5,7 +5,8 @@ LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[i32]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[i32]` to implement `Index` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 4457b7893d5d2..7f182a857871d 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -103,22 +103,6 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | | | variable not in all patterns -error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 - | -LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; - | - ^^^^ pattern doesn't bind `c` - | | - | variable not in all patterns - -error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 - | -LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; - | - ^^^^ pattern doesn't bind `d` - | | - | variable not in all patterns - error[E0408]: variable `e` is not bound in all patterns --> $DIR/missing-bindings.rs:45:10 | @@ -143,6 +127,22 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | | | variable not in all patterns +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns + +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `d` + | | + | variable not in all patterns + error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:61:29 | @@ -151,14 +151,6 @@ LL | Ok(a) | Err(_), | | | variable not in all patterns -error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:69:21 - | -LL | A(_, a) | - | - variable not in all patterns -LL | B(b), - | ^^^^ pattern doesn't bind `a` - error[E0408]: variable `b` is not bound in all patterns --> $DIR/missing-bindings.rs:68:21 | @@ -167,6 +159,14 @@ LL | A(_, a) | LL | B(b), | - variable not in all patterns +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:69:21 + | +LL | A(_, a) | + | - variable not in all patterns +LL | B(b), + | ^^^^ pattern doesn't bind `a` + error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:72:17 | @@ -185,6 +185,24 @@ LL | B(b), LL | B(_) | ^^^^ pattern doesn't bind `b` +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:57:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `b` +... +LL | B(b), + | - variable not in all patterns +... +LL | V3(c), + | ^^^^^ pattern doesn't bind `b` + error[E0408]: variable `c` is not bound in all patterns --> $DIR/missing-bindings.rs:57:13 | @@ -219,24 +237,6 @@ LL | A(_, a) | LL | V3(c), | ^^^^^ pattern doesn't bind `a` -error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 - | -LL | / V1( -LL | | -LL | | -LL | | A( -... | -LL | | B(Ok(a) | Err(a)) -LL | | ) | - | |_____________^ pattern doesn't bind `b` -... -LL | B(b), - | - variable not in all patterns -... -LL | V3(c), - | ^^^^^ pattern doesn't bind `b` - error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs index 775961d3fd740..ae27db7a83524 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs @@ -6,8 +6,5 @@ use core::panic::PanicInfo; #[panic_handler] -fn panic( - info: PanicInfo, //~ ERROR argument should be `&PanicInfo` -) -> () //~ ERROR return type should be `!` -{ -} +fn panic(info: PanicInfo) -> () {} +//~^ `#[panic_handler]` function has wrong type [E0308] diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr index 8b044f7669c72..85555c43906e8 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr @@ -1,14 +1,12 @@ -error: return type should be `!` - --> $DIR/panic-handler-bad-signature-1.rs:11:6 +error[E0308]: `#[panic_handler]` function has wrong type + --> $DIR/panic-handler-bad-signature-1.rs:9:16 | -LL | ) -> () - | ^^ - -error: argument should be `&PanicInfo` - --> $DIR/panic-handler-bad-signature-1.rs:10:11 +LL | fn panic(info: PanicInfo) -> () {} + | ^^^^^^^^^ expected `&PanicInfo<'_>`, found `PanicInfo<'_>` | -LL | info: PanicInfo, - | ^^^^^^^^^ + = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` + found signature `for<'a> fn(PanicInfo<'a>)` -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs index 727934000589a..3c3f1513f6fe8 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs @@ -6,9 +6,8 @@ use core::panic::PanicInfo; #[panic_handler] -fn panic( - info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo` -) -> ! +fn panic(info: &'static PanicInfo) -> ! +//~^ #[panic_handler]` function has wrong type [E0308] { loop {} } diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr index 5ab6934202e94..84eba2a5a63c2 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr @@ -1,8 +1,12 @@ -error: argument should be `&PanicInfo` - --> $DIR/panic-handler-bad-signature-2.rs:10:11 +error[E0308]: `#[panic_handler]` function has wrong type + --> $DIR/panic-handler-bad-signature-2.rs:9:1 | -LL | info: &'static PanicInfo, - | ^^^^^^^^^^^^^^^^^^ +LL | fn panic(info: &'static PanicInfo) -> ! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` + found signature `for<'a> fn(&'static PanicInfo<'a>) -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs index ab9c9d7f4177c..9e17e32fbb4cb 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs @@ -6,6 +6,6 @@ use core::panic::PanicInfo; #[panic_handler] -fn panic() -> ! { //~ ERROR function should have one argument +fn panic() -> ! { //~ #[panic_handler]` function has wrong type [E0308] loop {} } diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr index 0a70181fdace9..cdf55ab6534ea 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr @@ -1,8 +1,12 @@ -error: function should have one argument +error[E0308]: `#[panic_handler]` function has wrong type --> $DIR/panic-handler-bad-signature-3.rs:9:1 | LL | fn panic() -> ! { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` + found signature `fn() -> _` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.rs b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs new file mode 100644 index 0000000000000..97307d1b2a462 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs @@ -0,0 +1,13 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo<'static>) -> ! +//~^ #[panic_handler]` function has wrong type [E0308] +{ + loop {} +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr new file mode 100644 index 0000000000000..20c17587590ca --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr @@ -0,0 +1,12 @@ +error[E0308]: `#[panic_handler]` function has wrong type + --> $DIR/panic-handler-bad-signature-5.rs:9:1 + | +LL | fn panic(info: &PanicInfo<'static>) -> ! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` + found signature `for<'a> fn(&'a PanicInfo<'static>) -> _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.rs b/tests/ui/panic-handler/panic-handler-with-target-feature.rs new file mode 100644 index 0000000000000..8ea0275d7e99a --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-with-target-feature.rs @@ -0,0 +1,15 @@ +// compile-flags:-C panic=abort +// only-x86_64 + +#![feature(target_feature_11)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +#[target_feature(enable = "avx2")] +//~^ ERROR `panic_impl` language item function is not allowed to have `#[target_feature]` +fn panic(info: &PanicInfo) -> ! { + unimplemented!(); +} diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr new file mode 100644 index 0000000000000..4210a4200aee8 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr @@ -0,0 +1,11 @@ +error: `panic_impl` language item function is not allowed to have `#[target_feature]` + --> $DIR/panic-handler-with-target-feature.rs:11:1 + | +LL | #[target_feature(enable = "avx2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn panic(info: &PanicInfo) -> ! { + | ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]` + +error: aborting due to previous error + diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs index 38a80f8b6703a..751959f55bb6e 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs @@ -2,6 +2,7 @@ // run-fail // check-run-results // exec-env:RUST_BACKTRACE=1 +// needs-unwind // ignore-android FIXME #17520 // ignore-wasm no panic support // ignore-openbsd no support for libbacktrace without filename diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr index 2b648a0cad2ea..664ebaa4c51a6 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:57:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs index c872084f0333e..134e13233da51 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames.rs @@ -2,6 +2,7 @@ // run-fail // check-run-results // exec-env:RUST_BACKTRACE=1 +// needs-unwind // ignore-android FIXME #17520 // ignore-wasm no panic support // ignore-openbsd no support for libbacktrace without filename diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr index 5b37268409679..bc252fde1f6ab 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:53:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.rs b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs similarity index 100% rename from tests/ui/parser/assoc-const-underscore-semantic-fail.rs rename to tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/assoc-const-underscore-semantic-fail.stderr rename to tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr diff --git a/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs similarity index 100% rename from tests/ui/parser/assoc-const-underscore-syntactic-pass.rs rename to tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs diff --git a/tests/ui/parser/assoc-oddities-1.rs b/tests/ui/parser/assoc/assoc-oddities-1.rs similarity index 100% rename from tests/ui/parser/assoc-oddities-1.rs rename to tests/ui/parser/assoc/assoc-oddities-1.rs diff --git a/tests/ui/parser/assoc-oddities-1.stderr b/tests/ui/parser/assoc/assoc-oddities-1.stderr similarity index 100% rename from tests/ui/parser/assoc-oddities-1.stderr rename to tests/ui/parser/assoc/assoc-oddities-1.stderr diff --git a/tests/ui/parser/assoc-oddities-2.rs b/tests/ui/parser/assoc/assoc-oddities-2.rs similarity index 100% rename from tests/ui/parser/assoc-oddities-2.rs rename to tests/ui/parser/assoc/assoc-oddities-2.rs diff --git a/tests/ui/parser/assoc-oddities-2.stderr b/tests/ui/parser/assoc/assoc-oddities-2.stderr similarity index 100% rename from tests/ui/parser/assoc-oddities-2.stderr rename to tests/ui/parser/assoc/assoc-oddities-2.stderr diff --git a/tests/ui/parser/assoc-static-semantic-fail.rs b/tests/ui/parser/assoc/assoc-static-semantic-fail.rs similarity index 100% rename from tests/ui/parser/assoc-static-semantic-fail.rs rename to tests/ui/parser/assoc/assoc-static-semantic-fail.rs diff --git a/tests/ui/parser/assoc-static-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/assoc-static-semantic-fail.stderr rename to tests/ui/parser/assoc/assoc-static-semantic-fail.stderr diff --git a/tests/ui/parser/assoc-static-syntactic-fail.rs b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs similarity index 100% rename from tests/ui/parser/assoc-static-syntactic-fail.rs rename to tests/ui/parser/assoc/assoc-static-syntactic-fail.rs diff --git a/tests/ui/parser/assoc-static-syntactic-fail.stderr b/tests/ui/parser/assoc/assoc-static-syntactic-fail.stderr similarity index 100% rename from tests/ui/parser/assoc-static-syntactic-fail.stderr rename to tests/ui/parser/assoc/assoc-static-syntactic-fail.stderr diff --git a/tests/ui/parser/assoc-type-in-type-arg.rs b/tests/ui/parser/assoc/assoc-type-in-type-arg.rs similarity index 100% rename from tests/ui/parser/assoc-type-in-type-arg.rs rename to tests/ui/parser/assoc/assoc-type-in-type-arg.rs diff --git a/tests/ui/parser/assoc-type-in-type-arg.stderr b/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr similarity index 100% rename from tests/ui/parser/assoc-type-in-type-arg.stderr rename to tests/ui/parser/assoc/assoc-type-in-type-arg.stderr diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.rs similarity index 100% rename from tests/ui/parser/associated-types-project-from-hrtb-explicit.rs rename to tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.rs diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.stderr similarity index 100% rename from tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr rename to tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.stderr diff --git a/tests/ui/parser/attr-bad-meta-2.rs b/tests/ui/parser/attribute/attr-bad-meta-2.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta-2.rs rename to tests/ui/parser/attribute/attr-bad-meta-2.rs diff --git a/tests/ui/parser/attr-bad-meta-2.stderr b/tests/ui/parser/attribute/attr-bad-meta-2.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta-2.stderr rename to tests/ui/parser/attribute/attr-bad-meta-2.stderr diff --git a/tests/ui/parser/attr-bad-meta-3.rs b/tests/ui/parser/attribute/attr-bad-meta-3.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta-3.rs rename to tests/ui/parser/attribute/attr-bad-meta-3.rs diff --git a/tests/ui/parser/attr-bad-meta-3.stderr b/tests/ui/parser/attribute/attr-bad-meta-3.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta-3.stderr rename to tests/ui/parser/attribute/attr-bad-meta-3.stderr diff --git a/tests/ui/parser/attr-bad-meta.rs b/tests/ui/parser/attribute/attr-bad-meta.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta.rs rename to tests/ui/parser/attribute/attr-bad-meta.rs diff --git a/tests/ui/parser/attr-bad-meta.stderr b/tests/ui/parser/attribute/attr-bad-meta.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta.stderr rename to tests/ui/parser/attribute/attr-bad-meta.stderr diff --git a/tests/ui/parser/attr-before-eof.rs b/tests/ui/parser/attribute/attr-before-eof.rs similarity index 100% rename from tests/ui/parser/attr-before-eof.rs rename to tests/ui/parser/attribute/attr-before-eof.rs diff --git a/tests/ui/parser/attr-before-eof.stderr b/tests/ui/parser/attribute/attr-before-eof.stderr similarity index 100% rename from tests/ui/parser/attr-before-eof.stderr rename to tests/ui/parser/attribute/attr-before-eof.stderr diff --git a/tests/ui/parser/attr-dangling-in-fn.rs b/tests/ui/parser/attribute/attr-dangling-in-fn.rs similarity index 100% rename from tests/ui/parser/attr-dangling-in-fn.rs rename to tests/ui/parser/attribute/attr-dangling-in-fn.rs diff --git a/tests/ui/parser/attr-dangling-in-fn.stderr b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr similarity index 100% rename from tests/ui/parser/attr-dangling-in-fn.stderr rename to tests/ui/parser/attribute/attr-dangling-in-fn.stderr diff --git a/tests/ui/parser/attr-dangling-in-mod.rs b/tests/ui/parser/attribute/attr-dangling-in-mod.rs similarity index 100% rename from tests/ui/parser/attr-dangling-in-mod.rs rename to tests/ui/parser/attribute/attr-dangling-in-mod.rs diff --git a/tests/ui/parser/attr-dangling-in-mod.stderr b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr similarity index 100% rename from tests/ui/parser/attr-dangling-in-mod.stderr rename to tests/ui/parser/attribute/attr-dangling-in-mod.stderr diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs similarity index 100% rename from tests/ui/parser/attr-stmt-expr-attr-bad.rs rename to tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr similarity index 99% rename from tests/ui/parser/attr-stmt-expr-attr-bad.stderr rename to tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index 96899fd3fc5ca..e46c591080d43 100644 --- a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -27,6 +27,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files = note: outer attributes, like `#[test]`, annotate the item following them + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected expression, found `)` --> $DIR/attr-stmt-expr-attr-bad.rs:7:44 diff --git a/tests/ui/parser/attr-with-a-semicolon.rs b/tests/ui/parser/attribute/attr-with-a-semicolon.rs similarity index 100% rename from tests/ui/parser/attr-with-a-semicolon.rs rename to tests/ui/parser/attribute/attr-with-a-semicolon.rs diff --git a/tests/ui/parser/attr-with-a-semicolon.stderr b/tests/ui/parser/attribute/attr-with-a-semicolon.stderr similarity index 100% rename from tests/ui/parser/attr-with-a-semicolon.stderr rename to tests/ui/parser/attribute/attr-with-a-semicolon.stderr diff --git a/tests/ui/parser/attr.rs b/tests/ui/parser/attribute/attr.rs similarity index 100% rename from tests/ui/parser/attr.rs rename to tests/ui/parser/attribute/attr.rs diff --git a/tests/ui/parser/attr.stderr b/tests/ui/parser/attribute/attr.stderr similarity index 100% rename from tests/ui/parser/attr.stderr rename to tests/ui/parser/attribute/attr.stderr diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.rs similarity index 100% rename from tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs rename to tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.rs diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr similarity index 100% rename from tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr rename to tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr diff --git a/tests/ui/parser/attrs-after-extern-mod.rs b/tests/ui/parser/attribute/attrs-after-extern-mod.rs similarity index 100% rename from tests/ui/parser/attrs-after-extern-mod.rs rename to tests/ui/parser/attribute/attrs-after-extern-mod.rs diff --git a/tests/ui/parser/attrs-after-extern-mod.stderr b/tests/ui/parser/attribute/attrs-after-extern-mod.stderr similarity index 100% rename from tests/ui/parser/attrs-after-extern-mod.stderr rename to tests/ui/parser/attribute/attrs-after-extern-mod.stderr diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.rs b/tests/ui/parser/break-in-unlabeled-block-in-macro.rs new file mode 100644 index 0000000000000..eecc0026b12d6 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.rs @@ -0,0 +1,43 @@ +macro_rules! foo { + () => { + break (); //~ ERROR `break` outside of a loop or labeled block + }; + ($e: expr) => { + break $e; //~ ERROR `break` outside of a loop or labeled block + }; + (stmt $s: stmt) => { + $s + }; + (@ $e: expr) => { + { break $e; } //~ ERROR `break` outside of a loop or labeled block + }; + (=> $s: stmt) => { + { $s } + }; +} + +fn main() { + { + foo!(); + } + { + foo!(()); + } + { + foo!(stmt break ()); //~ ERROR `break` outside of a loop or labeled block + } + { + foo!(@ ()); + } + { + foo!(=> break ()); //~ ERROR `break` outside of a loop or labeled block + } + { + macro_rules! bar { + () => { + break () //~ ERROR `break` outside of a loop or labeled block + }; + } + bar!() + } +} diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr new file mode 100644 index 0000000000000..9407e8ac0029d --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr @@ -0,0 +1,69 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:3:9 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:6:9 + | +LL | break $e; + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(()); + | -------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19 + | +LL | foo!(stmt break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ foo!(stmt break 'block ()); + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:12:11 + | +LL | { break $e; } + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(@ ()); + | ---------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider labeling this block to be able to break within it + | +LL | 'block: { break 'block $e; } + | +++++++ ++++++ + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17 + | +LL | foo!(=> break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17 + | +LL | break () + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | bar!() + | ------ in this macro invocation + | + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/parser/break-in-unlabeled-block.fixed b/tests/ui/parser/break-in-unlabeled-block.fixed new file mode 100644 index 0000000000000..0885623252160 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.fixed @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + 'block: { + break 'block (); //~ ERROR `break` outside of a loop or labeled block + } + { + 'block: { + break 'block (); //~ ERROR `break` outside of a loop or labeled block + } + } +} diff --git a/tests/ui/parser/break-in-unlabeled-block.rs b/tests/ui/parser/break-in-unlabeled-block.rs new file mode 100644 index 0000000000000..3e5587e9f9c97 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.rs @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + { + break (); //~ ERROR `break` outside of a loop or labeled block + } + { + { + break (); //~ ERROR `break` outside of a loop or labeled block + } + } +} diff --git a/tests/ui/parser/break-in-unlabeled-block.stderr b/tests/ui/parser/break-in-unlabeled-block.stderr new file mode 100644 index 0000000000000..632cca80d8c03 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.stderr @@ -0,0 +1,27 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block.rs:4:9 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ break 'block (); + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block.rs:8:13 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ break 'block (); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/parser/expr-as-stmt.stderr b/tests/ui/parser/expr-as-stmt.stderr index 18c8b0b7c506b..76a83aa0161bb 100644 --- a/tests/ui/parser/expr-as-stmt.stderr +++ b/tests/ui/parser/expr-as-stmt.stderr @@ -217,7 +217,7 @@ LL | { true } || { true } | ^^^^^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:16]` + found closure `{closure@$DIR/expr-as-stmt.rs:51:14: 51:16}` help: parentheses are required to parse this as an expression | LL | ({ true }) || { true } diff --git a/tests/ui/parser/issues/issue-15980.rs b/tests/ui/parser/issues/issue-15980.rs index 87faa7d5ff1bf..eb7b6ca82969f 100644 --- a/tests/ui/parser/issues/issue-15980.rs +++ b/tests/ui/parser/issues/issue-15980.rs @@ -9,9 +9,6 @@ fn main(){ //~^ ERROR expected identifier, found keyword `return` //~| NOTE expected identifier, found keyword } - //~^ NOTE expected one of `.`, `=>`, `?`, or an operator _ => {} - //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` - //~| NOTE unexpected token } } diff --git a/tests/ui/parser/issues/issue-15980.stderr b/tests/ui/parser/issues/issue-15980.stderr index c59c811199ea8..cf8d011478766 100644 --- a/tests/ui/parser/issues/issue-15980.stderr +++ b/tests/ui/parser/issues/issue-15980.stderr @@ -11,15 +11,10 @@ help: escape `return` to use it as an identifier | LL | r#return | ++ - -error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` - --> $DIR/issue-15980.rs:13:9 +help: you might have meant to start a match arm after the match guard | -LL | } - | - expected one of `.`, `=>`, `?`, or an operator -LL | -LL | _ => {} - | ^ unexpected token +LL | Err(ref e) if e.kind == io::EndOfFile => { + | ++ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/tests/ui/parser/issues/issue-52496.stderr b/tests/ui/parser/issues/issue-52496.stderr index 77335c64c2120..78c81bf5b0df7 100644 --- a/tests/ui/parser/issues/issue-52496.stderr +++ b/tests/ui/parser/issues/issue-52496.stderr @@ -8,10 +8,15 @@ error: expected one of `,`, `:`, or `}`, found `.` --> $DIR/issue-52496.rs:8:22 | LL | let _ = Foo { bar.into(), bat: -1, . }; - | --- - ^ expected one of `,`, `:`, or `}` + | --- ---^ expected one of `,`, `:`, or `}` | | | - | | help: try naming a field: `bar:` + | | while parsing this struct field | while parsing this struct + | +help: try naming a field + | +LL | let _ = Foo { bar: bar.into(), bat: -1, . }; + | ++++ error: expected identifier, found `.` --> $DIR/issue-52496.rs:8:40 diff --git a/tests/ui/parser/issues/issue-84117.stderr b/tests/ui/parser/issues/issue-84117.stderr index 237bc11bd060d..958f3b40bb0eb 100644 --- a/tests/ui/parser/issues/issue-84117.stderr +++ b/tests/ui/parser/issues/issue-84117.stderr @@ -47,6 +47,7 @@ LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } | | | while parsing the type for `inner_local` | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: you might have meant to end the type parameters here | LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, } @@ -61,6 +62,8 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo | LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } | ^ expected one of 8 possible tokens + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` --> $DIR/issue-84117.rs:2:33 diff --git a/tests/ui/parser/issues/issue-89388.stderr b/tests/ui/parser/issues/issue-89388.stderr index cf28bef0f4ab0..366d05c2d9480 100644 --- a/tests/ui/parser/issues/issue-89388.stderr +++ b/tests/ui/parser/issues/issue-89388.stderr @@ -2,7 +2,12 @@ error: missing angle brackets in associated item path --> $DIR/issue-89388.rs:5:24 | LL | let _ = option.map([_]::to_vec); - | ^^^^^^^^^^^ help: try: `<[_]>::to_vec` + | ^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | let _ = option.map(<[_]>::to_vec); + | + + error: aborting due to previous error diff --git a/tests/ui/parser/issues/issue-89396.fixed b/tests/ui/parser/issues/issue-89396.fixed index 823ad8cd1f8df..0c040ddea44d4 100644 --- a/tests/ui/parser/issues/issue-89396.fixed +++ b/tests/ui/parser/issues/issue-89396.fixed @@ -8,9 +8,9 @@ fn main() { let _ = match opt { Some(_) => true, //~^ ERROR: expected one of - //~| HELP: try using a fat arrow here + //~| HELP: use a fat arrow to start a match arm None => false, //~^ ERROR: expected one of - //~| HELP: try using a fat arrow here + //~| HELP: use a fat arrow to start a match arm }; } diff --git a/tests/ui/parser/issues/issue-89396.rs b/tests/ui/parser/issues/issue-89396.rs index f1d9efa524f46..d95f666d797b6 100644 --- a/tests/ui/parser/issues/issue-89396.rs +++ b/tests/ui/parser/issues/issue-89396.rs @@ -8,9 +8,9 @@ fn main() { let _ = match opt { Some(_) = true, //~^ ERROR: expected one of - //~| HELP: try using a fat arrow here + //~| HELP: use a fat arrow to start a match arm None -> false, //~^ ERROR: expected one of - //~| HELP: try using a fat arrow here + //~| HELP: use a fat arrow to start a match arm }; } diff --git a/tests/ui/parser/issues/issue-89396.stderr b/tests/ui/parser/issues/issue-89396.stderr index 504420574e249..41ce07050746a 100644 --- a/tests/ui/parser/issues/issue-89396.stderr +++ b/tests/ui/parser/issues/issue-89396.stderr @@ -5,7 +5,7 @@ LL | Some(_) = true, | ^ | | | expected one of `=>`, `if`, or `|` - | help: try using a fat arrow here: `=>` + | help: use a fat arrow to start a match arm: `=>` error: expected one of `=>`, `@`, `if`, or `|`, found `->` --> $DIR/issue-89396.rs:12:14 @@ -14,7 +14,7 @@ LL | None -> false, | ^^ | | | expected one of `=>`, `@`, `if`, or `|` - | help: try using a fat arrow here: `=>` + | help: use a fat arrow to start a match arm: `=>` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-1.rs b/tests/ui/parser/issues/issue-98601-delimiter-error-1.rs new file mode 100644 index 0000000000000..cfbbd014d4f10 --- /dev/null +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-1.rs @@ -0,0 +1,9 @@ +fn foo() { + match 0 { + _ => {} + } + if foo + } +} //~ ERROR unexpected closing delimiter: `}` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr b/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr new file mode 100644 index 0000000000000..d568a4c583af1 --- /dev/null +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr @@ -0,0 +1,16 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-98601-delimiter-error-1.rs:7:1 + | +LL | fn foo() { + | - this delimiter might not be properly closed... +LL | match 0 { +LL | _ => {} + | -- block is empty, you might have not meant to close it +... +LL | } + | - ...as it matches this but it has different indentation +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.rs b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.rs new file mode 100644 index 0000000000000..254e816cfc9f6 --- /dev/null +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.rs @@ -0,0 +1,5 @@ +fn main() { + todo!(); +} + +fn other(_: i32)) {} //~ ERROR unexpected closing delimiter: `)` diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr new file mode 100644 index 0000000000000..81dd39bb7695c --- /dev/null +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr @@ -0,0 +1,14 @@ +error: unexpected closing delimiter: `)` + --> $DIR/issue-98601-delimiter-error-unexpected-close.rs:5:17 + | +LL | fn main() { + | - this opening brace... +LL | todo!(); +LL | } + | - ...matches this closing brace +LL | +LL | fn other(_: i32)) {} + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/macro-repeat.stderr b/tests/ui/parser/macro/macro-repeat.stderr index 63554b197b91c..ade2bbf9b0b05 100644 --- a/tests/ui/parser/macro/macro-repeat.stderr +++ b/tests/ui/parser/macro/macro-repeat.stderr @@ -9,6 +9,8 @@ error: variable 'v' is still repeating at this depth | LL | $v | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/missing-fat-arrow.rs b/tests/ui/parser/missing-fat-arrow.rs new file mode 100644 index 0000000000000..325f1ccf2fd93 --- /dev/null +++ b/tests/ui/parser/missing-fat-arrow.rs @@ -0,0 +1,38 @@ +fn main() { + let x = 1; + let y = 2; + let value = 3; + + match value { + Some(x) if x == y { + self.next_token()?; //~ ERROR expected identifier, found keyword `self` + }, + _ => {} + } + let _: i32 = (); //~ ERROR mismatched types +} + +struct Foo { + value: usize +} + +fn foo(a: Option<&mut Foo>, b: usize) { + match a { + Some(a) if a.value == b { + a.value = 1; //~ ERROR expected one of `,`, `:`, or `}`, found `.` + }, + _ => {} + } + let _: i32 = (); //~ ERROR mismatched types +} + +fn bar(a: Option<&mut Foo>, b: usize) { + match a { + Some(a) if a.value == b { + a.value, //~ ERROR expected one of `,`, `:`, or `}`, found `.` + } => { + } + _ => {} + } + let _: i32 = (); //~ ERROR mismatched types +} diff --git a/tests/ui/parser/missing-fat-arrow.stderr b/tests/ui/parser/missing-fat-arrow.stderr new file mode 100644 index 0000000000000..a6c786905e935 --- /dev/null +++ b/tests/ui/parser/missing-fat-arrow.stderr @@ -0,0 +1,78 @@ +error: expected identifier, found keyword `self` + --> $DIR/missing-fat-arrow.rs:8:13 + | +LL | Some(x) if x == y { + | - while parsing this struct +LL | self.next_token()?; + | ^^^^ expected identifier, found keyword + | +help: you might have meant to start a match arm after the match guard + | +LL | Some(x) if x == y => { + | ++ + +error: expected one of `,`, `:`, or `}`, found `.` + --> $DIR/missing-fat-arrow.rs:22:14 + | +LL | Some(a) if a.value == b { + | - while parsing this struct +LL | a.value = 1; + | -^ expected one of `,`, `:`, or `}` + | | + | while parsing this struct field + | +help: try naming a field + | +LL | a: a.value = 1; + | ++ +help: you might have meant to start a match arm after the match guard + | +LL | Some(a) if a.value == b => { + | ++ + +error: expected one of `,`, `:`, or `}`, found `.` + --> $DIR/missing-fat-arrow.rs:32:14 + | +LL | Some(a) if a.value == b { + | - while parsing this struct +LL | a.value, + | -^ expected one of `,`, `:`, or `}` + | | + | while parsing this struct field + | +help: try naming a field + | +LL | a: a.value, + | ++ +help: you might have meant to start a match arm after the match guard + | +LL | Some(a) if a.value == b => { + | ++ + +error[E0308]: mismatched types + --> $DIR/missing-fat-arrow.rs:12:18 + | +LL | let _: i32 = (); + | --- ^^ expected `i32`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/missing-fat-arrow.rs:26:18 + | +LL | let _: i32 = (); + | --- ^^ expected `i32`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/missing-fat-arrow.rs:37:18 + | +LL | let _: i32 = (); + | --- ^^ expected `i32`, found `()` + | | + | expected due to this + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr index 39eec80f658ad..37e93cbee7be7 100644 --- a/tests/ui/parser/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -25,10 +25,10 @@ LL | for ::Bar in x {} = help: consider removing `for<...>` error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/recover-quantified-closure.rs:2:25 + --> $DIR/recover-quantified-closure.rs:2:24 | LL | for<'a> |x: &'a u8| *x + 1; - | ------- ^ + | ------- ^ | | | `for<...>` is here diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax-with-2.stderr index c6ae1ce674ff8..e75c5bcd64319 100644 --- a/tests/ui/parser/removed-syntax-with-2.stderr +++ b/tests/ui/parser/removed-syntax-with-2.stderr @@ -2,8 +2,9 @@ error: expected one of `,`, `:`, or `}`, found `a` --> $DIR/removed-syntax-with-2.rs:8:31 | LL | let b = S { foo: (), with a }; - | - ^ expected one of `,`, `:`, or `}` - | | + | - ---- ^ expected one of `,`, `:`, or `}` + | | | + | | while parsing this struct field | while parsing this struct error[E0063]: missing field `bar` in initializer of `S` diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr index 0852c7cb4705d..c715486e2da9c 100644 --- a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -24,7 +24,7 @@ LL | | }.hi() { | |__________^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13]` + found closure `{closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13}` help: use parentheses to call this closure | LL ~ while (|| Foo { diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index c0a6558a1bf3b..0b432487615b2 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -307,6 +307,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0507]: cannot move out of `a` in pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 @@ -323,6 +324,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index dea7c4695cc18..43d92775e880c 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,10 +1,10 @@ -error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used in patterns +error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:9:9 | LL | const { || {} } => {}, | ^^^^^^^^^^^^^^^ -error: `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]` cannot be used in patterns +error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {}, diff --git a/tests/ui/pattern/patkind-litrange-no-expr.stderr b/tests/ui/pattern/patkind-litrange-no-expr.stderr index eb1ee7e45673d..45a2614894034 100644 --- a/tests/ui/pattern/patkind-litrange-no-expr.stderr +++ b/tests/ui/pattern/patkind-litrange-no-expr.stderr @@ -9,6 +9,8 @@ error: arbitrary expressions aren't allowed in patterns | LL | Arith = 1 + 1, | ^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/slice-patterns-irrefutable.stderr b/tests/ui/pattern/slice-patterns-irrefutable.stderr index fac99534f3e23..e98ee28d68686 100644 --- a/tests/ui/pattern/slice-patterns-irrefutable.stderr +++ b/tests/ui/pattern/slice-patterns-irrefutable.stderr @@ -3,6 +3,9 @@ error[E0282]: type annotations needed for `[_; 3]` | LL | let b; | ^ +LL | +LL | [a, b] = Default::default(); + | - type must be known at this point | help: consider giving `b` an explicit type, where the placeholders `_` are specified | diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs index 095f5ac9a8970..2616dfadb85e8 100644 --- a/tests/ui/pattern/usefulness/floats.rs +++ b/tests/ui/pattern/usefulness/floats.rs @@ -1,19 +1,45 @@ +#![feature(exclusive_range_pattern)] #![allow(illegal_floating_point_literal_pattern)] #![deny(unreachable_patterns)] fn main() { match 0.0 { - 0.0..=1.0 => {} - _ => {} // ok + 0.0..=1.0 => {} + _ => {} // ok } - match 0.0 { //~ ERROR non-exhaustive patterns - 0.0..=1.0 => {} + match 0.0 { + //~^ ERROR non-exhaustive patterns + 0.0..=1.0 => {} } match 1.0f64 { - 0.01f64 ..= 6.5f64 => {} - 0.02f64 => {} //~ ERROR unreachable pattern - _ => {} + 0.01f64..=6.5f64 => {} + 0.005f64 => {} + 0.01f64 => {} //~ ERROR unreachable pattern + 0.02f64 => {} //~ ERROR unreachable pattern + 6.5f64 => {} //~ ERROR unreachable pattern + 6.6f64 => {} + 1.0f64..=4.0f64 => {} //~ ERROR unreachable pattern + 5.0f64..=7.0f64 => {} + _ => {} + }; + match 1.0f64 { + 0.01f64..6.5f64 => {} + 6.5f64 => {} // this is reachable + _ => {} + }; + + match 1.0f32 { + 0.01f32..=6.5f32 => {} + 0.01f32 => {} //~ ERROR unreachable pattern + 0.02f32 => {} //~ ERROR unreachable pattern + 6.5f32 => {} //~ ERROR unreachable pattern + _ => {} + }; + match 1.0f32 { + 0.01f32..6.5f32 => {} + 6.5f32 => {} // this is reachable + _ => {} }; } diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index d66d4ba298bea..f50419118246b 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/floats.rs:10:11 + --> $DIR/floats.rs:11:11 | LL | match 0.0 { | ^^^ pattern `_` not covered @@ -7,22 +7,58 @@ LL | match 0.0 { = note: the matched value is of type `f64` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0.0..=1.0 => {}, -LL + _ => todo!() +LL ~ 0.0..=1.0 => {}, +LL + _ => todo!() | error: unreachable pattern - --> $DIR/floats.rs:16:7 + --> $DIR/floats.rs:19:9 | -LL | 0.02f64 => {} - | ^^^^^^^ +LL | 0.01f64 => {} + | ^^^^^^^ | note: the lint level is defined here - --> $DIR/floats.rs:2:9 + --> $DIR/floats.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: unreachable pattern + --> $DIR/floats.rs:20:9 + | +LL | 0.02f64 => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/floats.rs:21:9 + | +LL | 6.5f64 => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/floats.rs:23:9 + | +LL | 1.0f64..=4.0f64 => {} + | ^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/floats.rs:35:9 + | +LL | 0.01f32 => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/floats.rs:36:9 + | +LL | 0.02f32 => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/floats.rs:37:9 + | +LL | 6.5f32 => {} + | ^^^^^^ + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index 873def9031aaa..e1be98f85d847 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -1,4 +1,4 @@ -print-type-size type: `[async fn body@$DIR/async.rs:10:36: 13:2]`: 16386 bytes, alignment: 1 bytes +print-type-size type: `{async fn body@$DIR/async.rs:10:36: 13:2}`: 16386 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes @@ -16,14 +16,9 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment print-type-size variant `MaybeUninit`: 8192 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 8192 bytes -print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes -print-type-size discriminant: 1 bytes -print-type-size variant `Unresumed`: 0 bytes -print-type-size variant `Returned`: 0 bytes -print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1 bytes @@ -32,3 +27,8 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Pending`: 0 bytes +print-type-size type: `{async fn body@$DIR/async.rs:8:17: 8:19}`: 1 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/generator.stdout index 2dcadde9ec28b..f8c52a595cc4a 100644 --- a/tests/ui/print_type_sizes/generator.stdout +++ b/tests/ui/print_type_sizes/generator.stdout @@ -1,4 +1,4 @@ -print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes +print-type-size type: `{generator@$DIR/generator.rs:10:5: 10:14}`: 8193 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 8192 bytes print-type-size upvar `.array`: 8192 bytes diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout index fe0022cf5f4c9..f7bdee1112bce 100644 --- a/tests/ui/print_type_sizes/generator_discr_placement.stdout +++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout @@ -1,4 +1,4 @@ -print-type-size type: `[generator@$DIR/generator_discr_placement.rs:12:13: 12:15]`: 8 bytes, alignment: 4 bytes +print-type-size type: `{generator@$DIR/generator_discr_placement.rs:12:13: 12:15}`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 7 bytes diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr index f74f812e1a0ed..41d63532dea4a 100644 --- a/tests/ui/privacy/effective_visibilities.stderr +++ b/tests/ui/privacy/effective_visibilities.stderr @@ -45,6 +45,8 @@ error: not in the table | LL | struct PrivStruct; | ^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub --> $DIR/effective_visibilities.rs:25:9 @@ -81,6 +83,8 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl | LL | A( | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub --> $DIR/effective_visibilities.rs:38:17 diff --git a/tests/ui/privacy/effective_visibilities_full_priv.stderr b/tests/ui/privacy/effective_visibilities_full_priv.stderr index 29d82e2ee01c1..0577be1475fe4 100644 --- a/tests/ui/privacy/effective_visibilities_full_priv.stderr +++ b/tests/ui/privacy/effective_visibilities_full_priv.stderr @@ -9,6 +9,8 @@ error: not in the table | LL | struct Priv; | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) --> $DIR/effective_visibilities_full_priv.rs:13:5 diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index ca8f242e0bed2..a3552e146a65a 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -21,6 +21,7 @@ note: the module `baz` is defined here | LL | mod baz { | ^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0603]: module `baz` is private --> $DIR/privacy1.rs:141:18 diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index 6497b7ff535cb..ac7e5547de914 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -246,7 +246,7 @@ error: trait `traits_where::PrivTr` is more private than the item `traits_where: --> $DIR/private-in-public-warn.rs:68:5 | LL | impl Pub where T: PrivTr {} - | ^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` --> $DIR/private-in-public-warn.rs:55:5 diff --git a/tests/ui/privacy/private-in-public.stderr b/tests/ui/privacy/private-in-public.stderr index d8f9fd0071681..d3f7f0f637f5b 100644 --- a/tests/ui/privacy/private-in-public.stderr +++ b/tests/ui/privacy/private-in-public.stderr @@ -208,7 +208,7 @@ warning: trait `traits_where::PrivTr` is more private than the item `traits_wher --> $DIR/private-in-public.rs:52:5 | LL | impl Pub where T: PrivTr { - | ^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` --> $DIR/private-in-public.rs:42:5 diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index dcc249c635119..650766458465d 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -41,8 +41,11 @@ LL | struct PrivTy; warning: type `PrivTy` is more private than the item `S` --> $DIR/where-priv-type.rs:39:1 | -LL | impl S - | ^^^^^^ implementation `S` is reachable at visibility `pub` +LL | / impl S +LL | | +LL | | where +LL | | PrivTy: + | |___________^ implementation `S` is reachable at visibility `pub` | note: but type `PrivTy` is only usable at visibility `pub(crate)` --> $DIR/where-priv-type.rs:8:1 diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr index c476874332c57..ee79ce3f5d750 100644 --- a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr @@ -41,8 +41,11 @@ LL | trait PrivTr {} warning: trait `PrivTr` is more private than the item `S` --> $DIR/where-pub-type-impls-priv-trait.rs:41:1 | -LL | impl S - | ^^^^^^ implementation `S` is reachable at visibility `pub` +LL | / impl S +LL | | +LL | | where +LL | | PubTy: PrivTr + | |_________________^ implementation `S` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs index 739c25132e77b..3bea5d75779aa 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/mod.rs @@ -4,6 +4,7 @@ #![crate_type = "proc-macro"] #![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] +#![feature(proc_macro_byte_character)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs index 27391f8311176..07c9f464961ae 100644 --- a/tests/ui/proc-macro/auxiliary/api/parse.rs +++ b/tests/ui/proc-macro/auxiliary/api/parse.rs @@ -29,12 +29,16 @@ fn test_display_literal() { assert_eq!(Literal::character('\'').to_string(), "'\\''"); assert_eq!(Literal::character('"').to_string(), "'\"'"); assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'"); + + assert_eq!(Literal::byte_character(b'a').to_string(), "b'a'"); + assert_eq!(Literal::byte_character(0).to_string(), "b'\\x00'"); } fn test_parse_literal() { assert_eq!("1".parse::().unwrap().to_string(), "1"); assert_eq!("1.0".parse::().unwrap().to_string(), "1.0"); assert_eq!("'a'".parse::().unwrap().to_string(), "'a'"); + assert_eq!("b'a'".parse::().unwrap().to_string(), "b'a'"); assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); diff --git a/tests/ui/proc-macro/auxiliary/print-tokens.rs b/tests/ui/proc-macro/auxiliary/print-tokens.rs new file mode 100644 index 0000000000000..3a5767edb153d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/print-tokens.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree}; + +#[proc_macro] +pub fn print_tokens(input: TokenStream) -> TokenStream { + println!("{:#?}", input); + for token in input { + println!("{token}"); + } + TokenStream::new() +} diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr index e437bb90b1dfa..0a116d6f80d35 100644 --- a/tests/ui/proc-macro/issue-37788.stderr +++ b/tests/ui/proc-macro/issue-37788.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-37788.rs:8:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. LL | std::cell::Cell::new(0) | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stderr b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr index 6d1efb0dc281d..f3f470676e406 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.stderr +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr @@ -22,6 +22,7 @@ LL | #[derive(Print)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79202 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 2 warnings emitted diff --git a/tests/ui/proc-macro/literal-to-string.rs b/tests/ui/proc-macro/literal-to-string.rs new file mode 100644 index 0000000000000..494d17cbeeaff --- /dev/null +++ b/tests/ui/proc-macro/literal-to-string.rs @@ -0,0 +1,26 @@ +// check-pass +// edition: 2021 +#![feature(c_str_literals)] + +// aux-build: print-tokens.rs +extern crate print_tokens; + +fn main() { + print_tokens::print_tokens! { + 1 + 17u8 + 42. + 3.14f32 + b'a' + b'\xFF' + 'c' + '\x32' + "\"str\"" + r#""raw" str"# + r###"very ##"raw"## str"### + b"\"byte\" str" + br#""raw" "byte" str"# + c"\"c\" str" + cr#""raw" "c" str"# + } +} diff --git a/tests/ui/proc-macro/literal-to-string.stdout b/tests/ui/proc-macro/literal-to-string.stdout new file mode 100644 index 0000000000000..7b27fcf798b12 --- /dev/null +++ b/tests/ui/proc-macro/literal-to-string.stdout @@ -0,0 +1,107 @@ +TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: #0 bytes(172..173), + }, + Literal { + kind: Integer, + symbol: "17", + suffix: Some("u8"), + span: #0 bytes(182..186), + }, + Literal { + kind: Float, + symbol: "42.", + suffix: None, + span: #0 bytes(195..198), + }, + Literal { + kind: Float, + symbol: "3.14", + suffix: Some("f32"), + span: #0 bytes(207..214), + }, + Literal { + kind: Byte, + symbol: "a", + suffix: None, + span: #0 bytes(223..227), + }, + Literal { + kind: Byte, + symbol: "\xFF", + suffix: None, + span: #0 bytes(236..243), + }, + Literal { + kind: Char, + symbol: "c", + suffix: None, + span: #0 bytes(252..255), + }, + Literal { + kind: Char, + symbol: "\x32", + suffix: None, + span: #0 bytes(264..270), + }, + Literal { + kind: Str, + symbol: "\\"str\\"", + suffix: None, + span: #0 bytes(279..288), + }, + Literal { + kind: StrRaw(1), + symbol: "\"raw\" str", + suffix: None, + span: #0 bytes(297..311), + }, + Literal { + kind: StrRaw(3), + symbol: "very ##\"raw\"## str", + suffix: None, + span: #0 bytes(320..347), + }, + Literal { + kind: ByteStr, + symbol: "\\"byte\\" str", + suffix: None, + span: #0 bytes(356..371), + }, + Literal { + kind: ByteStrRaw(1), + symbol: "\"raw\" \"byte\" str", + suffix: None, + span: #0 bytes(380..402), + }, + Literal { + kind: CStr, + symbol: "\\"c\\" str", + suffix: None, + span: #0 bytes(411..423), + }, + Literal { + kind: CStrRaw(1), + symbol: "\"raw\" \"c\" str", + suffix: None, + span: #0 bytes(432..451), + }, +] +1 +17u8 +42. +3.14f32 +b'a' +b'\xFF' +'c' +'\x32' +"\"str\"" +r#""raw" str"# +r###"very ##"raw"## str"### +b"\"byte\" str" +br#""raw" "byte" str"# +c"\"c\" str" +cr#""raw" "c" str"# diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr index b9effe7cf21f3..0471124061ef4 100644 --- a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr +++ b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -143,6 +143,7 @@ LL | #[derive(my_macro)] | ^^^^^^^^ | = note: `my_macro` is in scope, but it is a function-like macro + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 20 previous errors diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr index 873054927c962..118882f73a3e4 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr @@ -18,6 +18,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 @@ -28,6 +29,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 @@ -38,6 +40,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -58,6 +61,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -68,6 +72,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -78,6 +83,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 8 previous errors diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr index 873054927c962..118882f73a3e4 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr @@ -18,6 +18,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 @@ -28,6 +29,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 @@ -38,6 +40,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -58,6 +61,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -68,6 +72,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: using an old version of `rental` --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 @@ -78,6 +83,7 @@ LL | enum ProceduralMasqueradeDummyType { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 8 previous errors diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr index 3c3f24d0ff22e..e7639f474c75e 100644 --- a/tests/ui/proc-macro/resolve-error.stderr +++ b/tests/ui/proc-macro/resolve-error.stderr @@ -44,6 +44,8 @@ error: cannot find derive macro `attr_proc_macra` in this scope | LL | #[derive(attr_proc_macra)] | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `Dlona` in this scope --> $DIR/resolve-error.rs:40:10 @@ -66,6 +68,8 @@ LL | #[derive(Dlona)] | LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { | ------------------------------------------------------- similarly named derive macro `Clona` defined here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `Dlone` in this scope --> $DIR/resolve-error.rs:35:10 @@ -84,6 +88,8 @@ LL | #[derive(Dlone)] --> $SRC_DIR/core/src/clone.rs:LL:COL | = note: similarly named derive macro `Clone` defined here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find attribute `FooWithLongNan` in this scope --> $DIR/resolve-error.rs:32:3 @@ -123,6 +129,8 @@ LL | #[derive(FooWithLongNan)] | LL | pub fn derive_foo(input: TokenStream) -> TokenStream { | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 14 previous errors diff --git a/tests/ui/proc-macro/resolved-located-at.stderr b/tests/ui/proc-macro/resolved-located-at.stderr index 0b4dbcba68287..a4f838521fdd6 100644 --- a/tests/ui/proc-macro/resolved-located-at.stderr +++ b/tests/ui/proc-macro/resolved-located-at.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/resolved-located-at.rs:7:27 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | resolve_located_at!(a b) | ^ expected `()`, found `S` | diff --git a/tests/ui/proc-macro/span-preservation.stderr b/tests/ui/proc-macro/span-preservation.stderr index 8c15cb9de9823..3ad9c539f8474 100644 --- a/tests/ui/proc-macro/span-preservation.stderr +++ b/tests/ui/proc-macro/span-preservation.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:39:5 | LL | extern "C" fn bar() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -46,7 +46,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:44:5 | LL | extern "C" fn baz() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -54,7 +54,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:49:5 | LL | extern "Rust" fn rust_abi() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:54:5 | LL | extern "\x43" fn c_abi_escaped() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer diff --git a/tests/ui/range/issue-54505-no-std.rs b/tests/ui/range/issue-54505-no-std.rs index db455fada3bd8..a15956853729a 100644 --- a/tests/ui/range/issue-54505-no-std.rs +++ b/tests/ui/range/issue-54505-no-std.rs @@ -17,9 +17,9 @@ extern "C" fn eh_personality() {} static EH_CATCH_TYPEINFO: u8 = 0; #[panic_handler] -fn panic_handler() {} -//~^ ERROR return type should be `!` -//~| ERROR function should have one argument +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + unimplemented!(); +} // take a reference to any built-in range fn take_range(_r: &impl RangeBounds) {} diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr index 13563d1940cb6..1694d514f4251 100644 --- a/tests/ui/range/issue-54505-no-std.stderr +++ b/tests/ui/range/issue-54505-no-std.stderr @@ -1,15 +1,3 @@ -error: return type should be `!` - --> $DIR/issue-54505-no-std.rs:20:20 - | -LL | fn panic_handler() {} - | ^ - -error: function should have one argument - --> $DIR/issue-54505-no-std.rs:20:1 - | -LL | fn panic_handler() {} - | ^^^^^^^^^^^^^^^^^^ - error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:29:16 | @@ -130,6 +118,6 @@ help: consider borrowing here LL | take_range(&(..=42)); | ++ + -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr index 543b7308472fe..5df8af484a9d1 100644 --- a/tests/ui/recursion/issue-83150.stderr +++ b/tests/ui/recursion/issue-83150.stderr @@ -9,12 +9,12 @@ LL | func(&mut iter.map(|x| x + 1)) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:13:24: 13:27]>: Iterator` +error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:13:24: 13:27]>` to implement `Iterator` + = note: required for `&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` = note: 65 redundant requirements hidden - = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/recursion_limit/empty.stderr b/tests/ui/recursion_limit/empty.stderr index cb5c0c35a5ebf..2f73067750706 100644 --- a/tests/ui/recursion_limit/empty.stderr +++ b/tests/ui/recursion_limit/empty.stderr @@ -13,6 +13,8 @@ LL | #![recursion_limit = ""] | ^^^^^^^^^^^^^^^^^^^^^--^ | | | `limit` must be a non-negative integer + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/recursion_limit/invalid_digit.stderr b/tests/ui/recursion_limit/invalid_digit.stderr index 4dc93ad5f67b3..4fda3039032a8 100644 --- a/tests/ui/recursion_limit/invalid_digit.stderr +++ b/tests/ui/recursion_limit/invalid_digit.stderr @@ -13,6 +13,8 @@ LL | #![recursion_limit = "-100"] | ^^^^^^^^^^^^^^^^^^^^^------^ | | | not a valid integer + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/recursion_limit/overflow.stderr b/tests/ui/recursion_limit/overflow.stderr index 2f622d28b45a1..6057177deb2f9 100644 --- a/tests/ui/recursion_limit/overflow.stderr +++ b/tests/ui/recursion_limit/overflow.stderr @@ -13,6 +13,8 @@ LL | #![recursion_limit = "999999999999999999999999"] | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ | | | `limit` is too large + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/regions/closure-in-projection-issue-97405.stderr b/tests/ui/regions/closure-in-projection-issue-97405.stderr index c08f1059ebf58..7070dfef138ac 100644 --- a/tests/ui/regions/closure-in-projection-issue-97405.stderr +++ b/tests/ui/regions/closure-in-projection-issue-97405.stderr @@ -3,27 +3,33 @@ error[E0310]: the associated type `::Item` may not li | LL | assert_static(opaque(async move { t; }).next()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::Item` must be valid for the static lifetime... + | ...so that the type `::Item` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:26:5 | LL | assert_static(opaque(move || { t; }).next()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::Item` must be valid for the static lifetime... + | ...so that the type `::Item` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:28:5 | LL | assert_static(opaque(opaque(async move { t; }).next()).next()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::Item` must be valid for the static lifetime... + | ...so that the type `::Item` will meet its required lifetime bounds | = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds error: aborting due to 3 previous errors diff --git a/tests/ui/regions/regions-close-associated-type-into-object.stderr b/tests/ui/regions/regions-close-associated-type-into-object.stderr index f7dcaa9d97e7c..6fb514377a6c2 100644 --- a/tests/ui/regions/regions-close-associated-type-into-object.stderr +++ b/tests/ui/regions/regions-close-associated-type-into-object.stderr @@ -3,36 +3,56 @@ error[E0310]: the associated type `::Item` may not live long enough | LL | Box::new(item) | ^^^^^^^^^^^^^^ + | | + | the associated type `::Item` must be valid for the static lifetime... + | ...so that the type `::Item` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound + | +LL | fn bad1(v: T) -> Box where ::Item: 'static + | ++++++++++++++++++++++++++++++++ error[E0310]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:22:5 | LL | Box::new(item) | ^^^^^^^^^^^^^^ + | | + | the associated type `::Item` must be valid for the static lifetime... + | ...so that the type `::Item` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | - = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +LL | where Box : X, ::Item: 'static + | ++++++++++++++++++++++++++++ error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:28:5 | +LL | fn bad3<'a, T: Iter>(v: T) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(item) - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound + | +LL | fn bad3<'a, T: Iter>(v: T) -> Box where ::Item: 'a + | +++++++++++++++++++++++++++ error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:35:5 | +LL | fn bad4<'a, T: Iter>(v: T) -> Box + | -- the associated type `::Item` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(item) - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ ...so that the type `::Item` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | - = help: consider adding an explicit lifetime bound `::Item: 'a`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +LL | where Box : X, ::Item: 'a + | +++++++++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/regions/regions-close-object-into-object-4.stderr b/tests/ui/regions/regions-close-object-into-object-4.stderr index 7a9f1ab00012f..b8b414b7e125e 100644 --- a/tests/ui/regions/regions-close-object-into-object-4.stderr +++ b/tests/ui/regions/regions-close-object-into-object-4.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/regions-close-object-into-object-4.rs:9:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | ^^^^^^^^ + | | + | the parameter type `U` must be valid for the static lifetime... + | ...so that the type `U` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { | +++++++++ @@ -13,9 +16,12 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/regions-close-object-into-object-4.rs:9:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `U` must be valid for the static lifetime... + | ...so that the type `U` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { | +++++++++ @@ -24,9 +30,13 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/regions-close-object-into-object-4.rs:9:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `U` must be valid for the static lifetime... + | ...so that the type `U` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound | LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { | +++++++++ @@ -61,9 +71,12 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/regions-close-object-into-object-4.rs:9:14 | LL | Box::new(B(&*v)) as Box - | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | ^^^^^^ + | | + | the parameter type `U` must be valid for the static lifetime... + | ...so that the type `U` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { | +++++++++ diff --git a/tests/ui/regions/regions-close-object-into-object-5.stderr b/tests/ui/regions/regions-close-object-into-object-5.stderr index 311e8868c0957..4a2f4f847a308 100644 --- a/tests/ui/regions/regions-close-object-into-object-5.stderr +++ b/tests/ui/regions/regions-close-object-into-object-5.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { | +++++++++ @@ -13,9 +16,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { | +++++++++ @@ -24,9 +30,13 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | Box::new(B(&*v)) as Box - | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound | LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { | +++++++++ @@ -44,9 +54,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:14 | LL | Box::new(B(&*v)) as Box - | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { | +++++++++ diff --git a/tests/ui/regions/regions-close-over-type-parameter-1.stderr b/tests/ui/regions/regions-close-over-type-parameter-1.stderr index b7b557d7a60a4..1cd5b7f225079 100644 --- a/tests/ui/regions/regions-close-over-type-parameter-1.stderr +++ b/tests/ui/regions/regions-close-over-type-parameter-1.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:11:5 | LL | Box::new(v) as Box - | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn make_object1(v: A) -> Box { | +++++++++ @@ -12,10 +15,12 @@ LL | fn make_object1(v: A) -> Box $DIR/regions-close-over-type-parameter-1.rs:20:5 | +LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { + | -- the parameter type `A` must be valid for the lifetime `'b` as defined here... LL | Box::new(v) as Box | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn make_object3<'a, 'b, A: SomeTrait + 'a + 'b>(v: A) -> Box { | ++++ diff --git a/tests/ui/regions/regions-close-param-into-object.stderr b/tests/ui/regions/regions-close-param-into-object.stderr index 9162be5b93cca..385441d328277 100644 --- a/tests/ui/regions/regions-close-param-into-object.stderr +++ b/tests/ui/regions/regions-close-param-into-object.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:6:5 | LL | Box::new(v) - | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | where T : X + 'static | +++++++++ @@ -13,9 +16,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:12:5 | LL | Box::new(v) - | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn p2(v: Box) -> Box | +++++++++ @@ -23,10 +29,13 @@ LL | fn p2(v: Box) -> Box error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:18:5 | +LL | fn p3<'a,T>(v: T) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(v) | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | where T : X + 'a | ++++ @@ -34,10 +43,13 @@ LL | where T : X + 'a error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:24:5 | +LL | fn p4<'a,T>(v: Box) -> Box + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +... LL | Box::new(v) | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn p4<'a,T: 'a>(v: Box) -> Box | ++++ diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr index 7c9f405563caa..8c1791fc11d76 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -1,10 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:5 | +LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) + | -- the parameter type `T` must be valid for the lifetime `'x` as defined here... +LL | { LL | wf::<&'x T>(); | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo) | ++++ diff --git a/tests/ui/regions/regions-infer-bound-from-trait-self.stderr b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr index e88f79a3a8c54..d0c4b9a57e096 100644 --- a/tests/ui/regions/regions-infer-bound-from-trait-self.stderr +++ b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr @@ -1,11 +1,16 @@ error[E0309]: the parameter type `Self` may not live long enough --> $DIR/regions-infer-bound-from-trait-self.rs:46:9 | +LL | trait InheritsFromNothing<'a> : Sized { + | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... +LL | fn foo(self, x: Inv<'a>) { LL | check_bound(x, self) - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `Self: 'a`... - = note: ...so that the type `Self` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound + | +LL | trait InheritsFromNothing<'a> : Sized where Self: 'a { + | ++++++++++++++ error: aborting due to previous error diff --git a/tests/ui/regions/regions-infer-bound-from-trait.stderr b/tests/ui/regions/regions-infer-bound-from-trait.stderr index 3ee71543d1570..b9be11a4639fe 100644 --- a/tests/ui/regions/regions-infer-bound-from-trait.stderr +++ b/tests/ui/regions/regions-infer-bound-from-trait.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:33:5 | +LL | fn bar1<'a,A>(x: Inv<'a>, a: A) { + | -- the parameter type `A` must be valid for the lifetime `'a` as defined here... LL | check_bound(x, a) | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) { | ++++ @@ -12,10 +14,12 @@ LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) { error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:37:5 | +LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) { + | -- the parameter type `A` must be valid for the lifetime `'a` as defined here... LL | check_bound(x, a) | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn bar2<'a,'b,A:Is<'b> + 'a>(x: Inv<'a>, y: Inv<'b>, a: A) { | ++++ diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2acfde4be46d9..d4fea2b192b48 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -5,7 +5,7 @@ // [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib // [msp430] needs-llvm-components: msp430 // [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib -#![feature(no_core, lang_items, intrinsics, staged_api)] +#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] #![stable(feature = "", since = "")] diff --git a/tests/ui/repr/repr-align-assign.stderr b/tests/ui/repr/repr-align-assign.stderr index b878ae0d17337..3606d02210ba0 100644 --- a/tests/ui/repr/repr-align-assign.stderr +++ b/tests/ui/repr/repr-align-assign.stderr @@ -15,12 +15,16 @@ error[E0693]: incorrect `repr(align)` attribute format | LL | #[repr(align=8)] | ^^^^^^^ help: use parentheses instead: `align(8)` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0693]: incorrect `repr(align)` attribute format --> $DIR/repr-align-assign.rs:9:8 | LL | #[repr(align="8")] | ^^^^^^^^^ help: use parentheses instead: `align(8)` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/repr/repr-align.stderr b/tests/ui/repr/repr-align.stderr index 900a811bb8ad7..84d33a08a6f5f 100644 --- a/tests/ui/repr/repr-align.stderr +++ b/tests/ui/repr/repr-align.stderr @@ -39,36 +39,48 @@ error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer | LL | #[repr(align(16.0))] | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0589]: invalid `repr(align)` attribute: not a power of two --> $DIR/repr-align.rs:7:8 | LL | #[repr(align(15))] | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0589]: invalid `repr(align)` attribute: larger than 2^29 --> $DIR/repr-align.rs:11:8 | LL | #[repr(align(4294967296))] | ^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer --> $DIR/repr-align.rs:18:8 | LL | #[repr(align(16.0))] | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0589]: invalid `repr(align)` attribute: not a power of two --> $DIR/repr-align.rs:22:8 | LL | #[repr(align(15))] | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0589]: invalid `repr(align)` attribute: larger than 2^29 --> $DIR/repr-align.rs:26:8 | LL | #[repr(align(4294967296))] | ^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 12 previous errors diff --git a/tests/ui/resolve/associated-fn-called-as-fn.stderr b/tests/ui/resolve/associated-fn-called-as-fn.stderr index fbdea30d551fd..7d28b959a1a48 100644 --- a/tests/ui/resolve/associated-fn-called-as-fn.stderr +++ b/tests/ui/resolve/associated-fn-called-as-fn.stderr @@ -2,13 +2,23 @@ error[E0425]: cannot find function `collect_primary` in this scope --> $DIR/associated-fn-called-as-fn.rs:6:30 | LL | '0'..='9' => collect_primary(&c), - | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + | ^^^^^^^^^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | '0'..='9' => Self::collect_primary(&c), + | ++++++ error[E0425]: cannot find function `collect_primary` in this scope --> $DIR/associated-fn-called-as-fn.rs:23:30 | LL | '0'..='9' => collect_primary(&c), - | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + | ^^^^^^^^^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | '0'..='9' => Self::collect_primary(&c), + | ++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/bad-expr-path.stderr b/tests/ui/resolve/bad-expr-path.stderr index 411130913c8f0..0392c1fa23993 100644 --- a/tests/ui/resolve/bad-expr-path.stderr +++ b/tests/ui/resolve/bad-expr-path.stderr @@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type LL | fn main(arguments: Vec) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn()` - found fn pointer `fn(Vec)` + = note: expected signature `fn()` + found signature `fn(Vec)` error[E0425]: cannot find function `log` in this scope --> $DIR/bad-expr-path.rs:4:5 diff --git a/tests/ui/resolve/bad-expr-path2.stderr b/tests/ui/resolve/bad-expr-path2.stderr index af3ca99c51024..9238b1f7023e5 100644 --- a/tests/ui/resolve/bad-expr-path2.stderr +++ b/tests/ui/resolve/bad-expr-path2.stderr @@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type LL | fn main(arguments: Vec) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn()` - found fn pointer `fn(Vec)` + = note: expected signature `fn()` + found signature `fn(Vec)` error[E0425]: cannot find function `log` in this scope --> $DIR/bad-expr-path2.rs:6:5 diff --git a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs new file mode 100644 index 0000000000000..b5f13959081b8 --- /dev/null +++ b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs @@ -0,0 +1,18 @@ +struct Foo { + field: u32, +} + +impl Foo { + fn field(&self) -> u32 { + self.field + } + + fn new() -> Foo { + field; //~ ERROR cannot find value `field` in this scope + Foo { field } //~ ERROR cannot find value `field` in this scope + } + fn clone(&self) -> Foo { + Foo { field } //~ ERROR cannot find value `field` in this scope + } +} +fn main() {} diff --git a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr new file mode 100644 index 0000000000000..3c44c1c249ce2 --- /dev/null +++ b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr @@ -0,0 +1,41 @@ +error[E0425]: cannot find value `field` in this scope + --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9 + | +LL | field: u32, + | ---------- a field by that name exists in `Self` +... +LL | fn field(&self) -> u32 { + | ----- a method by that name is available on `Self` here +... +LL | field; + | ^^^^^ + +error[E0425]: cannot find value `field` in this scope + --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15 + | +LL | field: u32, + | ---------- a field by that name exists in `Self` +... +LL | fn field(&self) -> u32 { + | ----- a method by that name is available on `Self` here +... +LL | Foo { field } + | ^^^^^ + +error[E0425]: cannot find value `field` in this scope + --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:15:15 + | +LL | fn field(&self) -> u32 { + | ----- a method by that name is available on `Self` here +... +LL | Foo { field } + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | Foo { field: self.field } + | ++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-103474.stderr b/tests/ui/resolve/issue-103474.stderr index 415d231552a03..e48fb31eccc9a 100644 --- a/tests/ui/resolve/issue-103474.stderr +++ b/tests/ui/resolve/issue-103474.stderr @@ -19,7 +19,7 @@ error[E0425]: cannot find function `first` in this scope LL | first() | ^^^^^ not found in this scope | -help: consider using the associated function +help: consider using the method on `Self` | LL | self.first() | +++++ diff --git a/tests/ui/resolve/issue-116164.rs b/tests/ui/resolve/issue-116164.rs new file mode 100644 index 0000000000000..d30c8f514b3d6 --- /dev/null +++ b/tests/ui/resolve/issue-116164.rs @@ -0,0 +1,19 @@ +#![allow(unused_imports)] + +mod inner { + pub enum Example { + ExOne, + } +} + +mod reexports { + pub use crate::inner::Example as _; +} + +use crate::reexports::*; +//~^ SUGGESTION: use inner::Example::ExOne + +fn main() { + ExOne; + //~^ ERROR: cannot find value `ExOne` in this scope +} diff --git a/tests/ui/resolve/issue-116164.stderr b/tests/ui/resolve/issue-116164.stderr new file mode 100644 index 0000000000000..5820a189fd572 --- /dev/null +++ b/tests/ui/resolve/issue-116164.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find value `ExOne` in this scope + --> $DIR/issue-116164.rs:17:5 + | +LL | ExOne; + | ^^^^^ not found in this scope + | +help: consider importing this unit variant + | +LL + use inner::Example::ExOne; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-14254.stderr b/tests/ui/resolve/issue-14254.stderr index 690a40f7edd77..9284b4babc50f 100644 --- a/tests/ui/resolve/issue-14254.stderr +++ b/tests/ui/resolve/issue-14254.stderr @@ -8,13 +8,23 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:30:9 | LL | x; - | ^ help: you might have meant to use the available field: `self.x` + | ^ + | +help: you might have meant to use the available field + | +LL | self.x; + | +++++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:32:9 | LL | y; - | ^ help: you might have meant to use the available field: `self.y` + | ^ + | +help: you might have meant to use the available field + | +LL | self.y; + | +++++ error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:34:9 @@ -31,7 +41,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:38:9 @@ -43,13 +53,23 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:47:9 | LL | x; - | ^ help: you might have meant to use the available field: `self.x` + | ^ + | +help: you might have meant to use the available field + | +LL | self.x; + | +++++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:49:9 | LL | y; - | ^ help: you might have meant to use the available field: `self.y` + | ^ + | +help: you might have meant to use the available field + | +LL | self.y; + | +++++ error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:51:9 @@ -66,7 +86,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:55:9 @@ -83,7 +103,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:73:9 @@ -94,7 +114,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:82:9 @@ -105,7 +125,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:91:9 @@ -116,7 +136,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:100:9 @@ -127,55 +147,95 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:19:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:28:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:45:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:62:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:71:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:80:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:89:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:98:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error: aborting due to 24 previous errors diff --git a/tests/ui/resolve/issue-2356.stderr b/tests/ui/resolve/issue-2356.stderr index 30f5f05952664..5f75ae988702f 100644 --- a/tests/ui/resolve/issue-2356.stderr +++ b/tests/ui/resolve/issue-2356.stderr @@ -1,8 +1,11 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:39:5 | +LL | whiskers: isize, + | --------------- a field by that name exists in `Self` +... LL | whiskers -= other; - | ^^^^^^^^ a field by this name exists in `Self` + | ^^^^^^^^ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 @@ -21,13 +24,21 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:79:5 | LL | whiskers = 0; - | ^^^^^^^^ help: you might have meant to use the available field: `self.whiskers` + | ^^^^^^^^ + | +help: you might have meant to use the available field + | +LL | self.whiskers = 0; + | +++++ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:84:5 | +LL | whiskers: isize, + | --------------- a field by that name exists in `Self` +... LL | whiskers = 4; - | ^^^^^^^^ a field by this name exists in `Self` + | ^^^^^^^^ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 @@ -47,19 +58,34 @@ error[E0425]: cannot find function `clone` in this scope --> $DIR/issue-2356.rs:24:5 | LL | clone(); - | ^^^^^ help: you might have meant to call the method: `self.clone` + | ^^^^^ + | +help: you might have meant to call the method + | +LL | 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` + | ^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | Self::default(); + | ++++++ error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:41:5 | LL | shave(4); - | ^^^^^ help: you might have meant to call the associated function: `Self::shave` + | ^^^^^ + | +help: you might have meant to call the associated function + | +LL | Self::shave(4); + | ++++++ error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:43:5 @@ -73,7 +99,7 @@ error[E0425]: cannot find function `static_method` in this scope LL | static_method(); | ^^^^^^^^^^^^^ not found in this scope | -help: consider using the associated function +help: consider using the associated function on `Self` | LL | Self::static_method(); | ++++++ @@ -102,7 +128,7 @@ error[E0425]: cannot find function `grow_older` in this scope LL | grow_older(); | ^^^^^^^^^^ not found in this scope | -help: consider using the associated function +help: consider using the associated function on `Self` | LL | Self::grow_older(); | ++++++ diff --git a/tests/ui/resolve/issue-60057.stderr b/tests/ui/resolve/issue-60057.stderr index 4d915fcd9fe3d..a2ab86443536c 100644 --- a/tests/ui/resolve/issue-60057.stderr +++ b/tests/ui/resolve/issue-60057.stderr @@ -1,14 +1,22 @@ error[E0425]: cannot find value `banana` in this scope --> $DIR/issue-60057.rs:8:21 | +LL | banana: u8, + | ---------- a field by that name exists in `Self` +... LL | banana: banana - | ^^^^^^ a field by this name exists in `Self` + | ^^^^^^ error[E0425]: cannot find value `banana` in this scope --> $DIR/issue-60057.rs:14:21 | LL | banana: banana - | ^^^^^^ help: you might have meant to use the available field: `self.banana` + | ^^^^^^ + | +help: you might have meant to use the available field + | +LL | banana: self.banana + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/resolve-assoc-suggestions.stderr b/tests/ui/resolve/resolve-assoc-suggestions.stderr index 8def9aa20253b..3d9d4ffaa10c8 100644 --- a/tests/ui/resolve/resolve-assoc-suggestions.stderr +++ b/tests/ui/resolve/resolve-assoc-suggestions.stderr @@ -14,13 +14,23 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:20:9 | LL | field; - | ^^^^^ help: you might have meant to use the available field: `self.field` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.field; + | +++++ error[E0412]: cannot find type `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:23:16 | LL | let _: Type; - | ^^^^ help: you might have meant to use the associated type: `Self::Type` + | ^^^^ + | +help: you might have meant to use the associated type + | +LL | let _: Self::Type; + | ++++++ error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:25:13 @@ -50,7 +60,12 @@ error[E0425]: cannot find value `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:34:9 | LL | method; - | ^^^^^^ help: you might have meant to refer to the method: `self.method` + | ^^^^^^ + | +help: you might have meant to refer to the method + | +LL | self.method; + | +++++ error: aborting due to 9 previous errors diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr index 42b7281d7b060..d6240fb8f872c 100644 --- a/tests/ui/resolve/resolve-inconsistent-names.stderr +++ b/tests/ui/resolve/resolve-inconsistent-names.stderr @@ -1,11 +1,3 @@ -error[E0408]: variable `a` is not bound in all patterns - --> $DIR/resolve-inconsistent-names.rs:13:12 - | -LL | a | b => {} - | - ^ pattern doesn't bind `a` - | | - | variable not in all patterns - error[E0408]: variable `b` is not bound in all patterns --> $DIR/resolve-inconsistent-names.rs:13:8 | @@ -14,6 +6,14 @@ LL | a | b => {} | | | pattern doesn't bind `b` +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:13:12 + | +LL | a | b => {} + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns + error[E0408]: variable `c` is not bound in all patterns --> $DIR/resolve-inconsistent-names.rs:19:9 | @@ -54,6 +54,19 @@ LL | (A, B) | (ref B, c) | (c, A) => () | | | first binding +error[E0408]: variable `Const2` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:31:9 + | +LL | (CONST1, _) | (_, Const2) => () + | ^^^^^^^^^^^ ------ variable not in all patterns + | | + | pattern doesn't bind `Const2` + | +help: if you meant to match on constant `m::Const2`, use the full path in the pattern + | +LL | (CONST1, _) | (_, m::Const2) => () + | ~~~~~~~~~ + error[E0408]: variable `CONST1` is not bound in all patterns --> $DIR/resolve-inconsistent-names.rs:31:23 | @@ -68,19 +81,6 @@ note: you might have meant to match on constant `m::CONST1`, which exists but is LL | const CONST1: usize = 10; | ^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible -error[E0408]: variable `Const2` is not bound in all patterns - --> $DIR/resolve-inconsistent-names.rs:31:9 - | -LL | (CONST1, _) | (_, Const2) => () - | ^^^^^^^^^^^ ------ variable not in all patterns - | | - | pattern doesn't bind `Const2` - | -help: if you meant to match on constant `m::Const2`, use the full path in the pattern - | -LL | (CONST1, _) | (_, m::Const2) => () - | ~~~~~~~~~ - error[E0308]: mismatched types --> $DIR/resolve-inconsistent-names.rs:19:19 | diff --git a/tests/ui/resolve/resolve-speculative-adjustment.stderr b/tests/ui/resolve/resolve-speculative-adjustment.stderr index be11a7ebeca00..fb15472bdae8d 100644 --- a/tests/ui/resolve/resolve-speculative-adjustment.stderr +++ b/tests/ui/resolve/resolve-speculative-adjustment.stderr @@ -8,13 +8,23 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:23:9 | LL | field; - | ^^^^^ help: you might have meant to use the available field: `self.field` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.field; + | +++++ error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:25:9 | LL | method(); - | ^^^^^^ help: you might have meant to call the method: `self.method` + | ^^^^^^ + | +help: you might have meant to call the method + | +LL | self.method(); + | +++++ error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:19:13 diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr index f32e0404e46cb..0306c8af87d85 100644 --- a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -1,20 +1,20 @@ error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16 | +LL | config: String, + | -------------- a field by that name exists in `Self` +... LL | Self { config } - | ^^^^^^ - | | - | a field by this name exists in `Self` - | help: a local variable with a similar name exists: `cofig` + | ^^^^^^ help: a local variable with a similar name exists: `cofig` error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20 | +LL | config: String, + | -------------- a field by that name exists in `Self` +... LL | println!("{config}"); - | ^^^^^^ - | | - | a field by this name exists in `Self` - | help: a local variable with a similar name exists: `cofig` + | ^^^^^^ help: a local variable with a similar name exists: `cofig` error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20 @@ -25,7 +25,7 @@ LL | println!("{config}"); help: you might have meant to use the available field | LL | println!("{self.config}"); - | ~~~~~~~~~~~ + | +++++ help: a local variable with a similar name exists | LL | println!("{cofig}"); @@ -43,7 +43,7 @@ LL | fn ba() {} help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ help: a function with a similar name exists | LL | ba; @@ -61,7 +61,7 @@ LL | const BARR: u32 = 3; help: you might have meant to use the associated `const` | LL | Self::BAR; - | ~~~~~~~~~ + | ++++++ help: a constant with a similar name exists | LL | BARR; @@ -79,7 +79,7 @@ LL | type Bar = String; help: you might have meant to use the associated type | LL | let foo: Self::Baz = "".to_string(); - | ~~~~~~~~~ + | ++++++ help: a type alias with a similar name exists | LL | let foo: Bar = "".to_string(); @@ -97,7 +97,7 @@ LL | fn ba() {} help: you might have meant to call the method | LL | self.baz(); - | ~~~~~~~~ + | +++++ help: a function with a similar name exists | LL | ba(); diff --git a/tests/ui/resolve/unresolved_static_type_field.stderr b/tests/ui/resolve/unresolved_static_type_field.stderr index 06926b53ddd35..035dc9b9656ad 100644 --- a/tests/ui/resolve/unresolved_static_type_field.stderr +++ b/tests/ui/resolve/unresolved_static_type_field.stderr @@ -1,8 +1,11 @@ error[E0425]: cannot find value `cx` in this scope --> $DIR/unresolved_static_type_field.rs:9:11 | +LL | cx: bool, + | -------- a field by that name exists in `Self` +... LL | f(cx); - | ^^ a field by this name exists in `Self` + | ^^ error: aborting due to previous error diff --git a/tests/ui/return/return-struct.stderr b/tests/ui/return/return-struct.stderr index e6c0363e36310..282e6498ebe3e 100644 --- a/tests/ui/return/return-struct.stderr +++ b/tests/ui/return/return-struct.stderr @@ -17,7 +17,7 @@ error[E0308]: mismatched types --> $DIR/return-struct.rs:15:5 | LL | fn bar() { - | - help: try adding a return type: `-> Age` + | - help: try adding a return type: `-> Age` LL | let mut age = 29; LL | Age::Years(age, 55) | ^^^^^^^^^^^^^^^^^^^ expected `()`, found `Age` @@ -26,7 +26,7 @@ error[E0308]: mismatched types --> $DIR/return-struct.rs:20:5 | LL | fn baz() { - | - help: try adding a return type: `-> S` + | - help: try adding a return type: `-> S` LL | S | ^ expected `()`, found `S` diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr index d183eaaa6236e..5f8c5dbe61938 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr @@ -15,6 +15,7 @@ LL | f: &id, | = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` found trait `Fn<(&Foo<'_>,)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623-2.rs:28:8 diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs index 0cab47170631b..f0e111b578f9f 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs @@ -1,7 +1,7 @@ #![feature(start)] #[start] -#[track_caller] //~ ERROR `start` is not allowed to be `#[track_caller]` +#[track_caller] //~ ERROR `#[start]` function is not allowed to be `#[track_caller]` fn start(_argc: isize, _argv: *const *const u8) -> isize { panic!("{}: oh no", std::panic::Location::caller()); } diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr index 454c98ff93437..b6ef6215275e8 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr @@ -1,10 +1,10 @@ -error: `start` is not allowed to be `#[track_caller]` +error: `#[start]` function is not allowed to be `#[track_caller]` --> $DIR/error-with-start.rs:4:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { - | -------------------------------------------------------- `start` is not allowed to be `#[track_caller]` + | -------------------------------------------------------- `#[start]` function is not allowed to be `#[track_caller]` error: aborting due to previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr index 0c388f5fe411b..041f7ebc0aa1d 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -2,14 +2,17 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/dont-infer-static.rs:6:10 | LL | bar: Bar - | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds... + | ^^^^^^ + | | + | the parameter type `U` must be valid for the static lifetime... + | ...so that the type `U` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/dont-infer-static.rs:8:15 | LL | struct Bar { | ^^^^^^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | struct Foo { | +++++++++ diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index 2c660b2850097..5b605f3eef569 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:17:18 | +LL | enum Ref1<'a, T> { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | enum Ref1<'a, T: 'a> { | ++++ @@ -12,10 +14,13 @@ LL | enum Ref1<'a, T: 'a> { error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:22:25 | +LL | enum Ref2<'a, T> { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | enum Ref2<'a, T: 'a> { | ++++ @@ -23,10 +28,12 @@ LL | enum Ref2<'a, T: 'a> { error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:23 | +LL | enum RefDouble<'a, 'b, T> { + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | enum RefDouble<'a, 'b, T: 'b> { | ++++ diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index 34ff1362cf323..eb17ce736f766 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:13:16 | +LL | impl<'a, T> Trait<'a, T> for usize { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Out = &'a T; | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for usize { | ++++ @@ -12,6 +14,8 @@ LL | impl<'a, T: 'a> Trait<'a, T> for usize { error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:21:16 | +LL | impl<'a, T> Trait<'a, T> for u32 { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Out = RefOk<'a, T>; | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... | @@ -20,7 +24,7 @@ note: ...that is required by this bound | LL | struct RefOk<'a, T:'a> { | ^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for u32 { | ++++ diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs index 50e8ce2fdd5ed..221c0416dbf70 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs @@ -5,5 +5,5 @@ #[start] #[target_feature(enable = "avx2")] -//~^ ERROR `start` is not allowed to have `#[target_feature]` +//~^ ERROR `#[start]` function is not allowed to have `#[target_feature]` fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr index 07687f3c7f4a2..b49f8afd960da 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr @@ -1,11 +1,11 @@ -error: `start` is not allowed to have `#[target_feature]` +error: `#[start]` function is not allowed to have `#[target_feature]` --> $DIR/issue-108645-target-feature-on-start.rs:7:1 | LL | #[target_feature(enable = "avx2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } - | -------------------------------------------------------- `start` is not allowed to have `#[target_feature]` + | -------------------------------------------------------- `#[start]` function is not allowed to have `#[target_feature]` error: aborting due to previous error diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs deleted file mode 100644 index f8e033937c607..0000000000000 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags:--extern му_сгате -// edition:2018 - -use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате` - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr deleted file mode 100644 index 05fc4fb22ad1e..0000000000000 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot load a crate with a non-ascii name `му_сгате` - --> $DIR/crate_name_nonascii_forbidden-2.rs:4:5 - | -LL | use му_сгате::baz; - | ^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs similarity index 100% rename from tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs rename to tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr similarity index 75% rename from tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr rename to tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr index a8f3abe599eb2..5aade17cba52d 100644 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr +++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr @@ -1,5 +1,5 @@ error: cannot load a crate with a non-ascii name `ьаг` - --> $DIR/crate_name_nonascii_forbidden-1.rs:1:1 + --> $DIR/crate_name_nonascii_forbidden.rs:1:1 | LL | extern crate ьаг; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs index 2c99d8bf1c677..15f062edf0ede 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl, const_closures)] #![allow(incomplete_features)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr new file mode 100644 index 0000000000000..f25390a9070e1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr @@ -0,0 +1,8 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-parse-not-item.rs:7:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index 96ffca6519ab4..4c45b0e56c601 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -1,15 +1,8 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closure-trait-method-fail.rs:15:5 +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-trait-method-fail.rs:14:39 | -LL | x(()) - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { - | ++++++++++++++++++++++++++++++++ +LL | const fn need_const_closure i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index fd0c29118145f..a8ef244ea3092 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -1,15 +1,8 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closure-trait-method.rs:15:5 +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-trait-method.rs:14:39 | -LL | x(()) - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { - | ++++++++++++++++++++++++++++++++ +LL | const fn need_const_closure i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index abf2a2dc511d1..6d61b23e4b7c3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -1,39 +1,26 @@ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:12:5 +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:8:19 | -LL | f() * 7 - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, - | +++++++++++++++++++++++++ +LL | F: ~const FnOnce() -> u8, + | ^^^^^^^^^^^^^^ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:24:5 - | -LL | f() + f() - | ^^^ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:9:19 | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { - | +++++++++++++++++++++++++ +LL | F: ~const FnMut() -> u8, + | ^^^^^^^^^^^^^ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:24:11 - | -LL | f() + f() - | ^^^ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:10:19 | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound +LL | F: ~const Fn() -> u8, + | ^^^^^^^^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:23:27 | -LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { - | +++++++++++++++++++++++++ +LL | const fn answer u8>(f: &F) -> u8 { + | ^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs new file mode 100644 index 0000000000000..1e22ddcea8d3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs @@ -0,0 +1,28 @@ +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait MyTrait { + fn do_something(&self); +} + +trait OtherTrait { + fn do_something_else() where Self: ~const MyTrait; + //~^ ERROR `~const` is not allowed here +} + +struct MyStruct(T); + +impl const MyTrait for u32 { + fn do_something(&self) {} +} + +impl MyStruct { + pub fn foo(&self) where T: ~const MyTrait { + //~^ ERROR `~const` is not allowed here + self.0.do_something(); + } +} + +fn main() { + MyStruct(0u32).foo(); +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr new file mode 100644 index 0000000000000..9210f6427064f --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr @@ -0,0 +1,26 @@ +error: `~const` is not allowed here + --> $DIR/const-bound-on-not-const-associated-fn.rs:9:40 + | +LL | fn do_something_else() where Self: ~const MyTrait; + | ^^^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/const-bound-on-not-const-associated-fn.rs:9:8 + | +LL | fn do_something_else() where Self: ~const MyTrait; + | ^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/const-bound-on-not-const-associated-fn.rs:20:32 + | +LL | pub fn foo(&self) where T: ~const MyTrait { + | ^^^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/const-bound-on-not-const-associated-fn.rs:20:12 + | +LL | pub fn foo(&self) where T: ~const MyTrait { + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs new file mode 100644 index 0000000000000..2f474d978d3b3 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(const_trait_impl, effects)] + +const fn a() {} + +fn foo(a: F) {} + +fn main() { + let _ = a; + foo(a); +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr index 8bf00eaff1fb9..e8ae7e4e36cef 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr @@ -13,6 +13,7 @@ LL | use core::convert::{From, TryFrom}; | ^^^^ maybe a missing crate `core`? | = help: consider adding `extern crate core` to use the `core` crate + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index 97f346e8c1dba..b60399c57dca9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits | LL | trait Bar: ~const Foo {} | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index 97f346e8c1dba..b60399c57dca9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits | LL | trait Bar: ~const Foo {} | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index 2897eabb08158..eb12a236d8c30 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits | LL | trait Bar: ~const Foo {} | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:17:24 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index 9839a4f2480bf..cd0ee73277d60 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits | LL | trait Bar: ~const Foo {} | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs index 89d74cecfdb77..4b720b534a49e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs @@ -7,7 +7,8 @@ struct Foo; impl Foo { fn add(self) -> Foo<{ A::add(N) }> { - //~^ ERROR mismatched types + //~^ ERROR `~const` is not allowed here + //~| ERROR mismatched types Foo } } @@ -30,7 +31,7 @@ fn bar(_: Foo) -> Foo<{ A::add(N) }> { } fn main() { - let foo = Foo::<0>; - let foo = bar::<(), _>(foo); - let _foo = bar::<(), _>(foo); + let foo = Foo::<0>; + let foo = bar::<(), _>(foo); + let _foo = bar::<(), _>(foo); } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr index ec5d21d33c6e6..be7a83dc18411 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -1,17 +1,29 @@ error: `~const` is not allowed here - --> $DIR/tilde-const-and-const-params.rs:26:11 + --> $DIR/tilde-const-and-const-params.rs:9:15 + | +LL | fn add(self) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-and-const-params.rs:9:8 + | +LL | fn add(self) -> Foo<{ A::add(N) }> { + | ^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-and-const-params.rs:27:11 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^^^^^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/tilde-const-and-const-params.rs:26:4 + --> $DIR/tilde-const-and-const-params.rs:27:4 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^ error[E0308]: mismatched types - --> $DIR/tilde-const-and-const-params.rs:26:61 + --> $DIR/tilde-const-and-const-params.rs:27:61 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^^^^^^^ expected `false`, found `true` @@ -28,6 +40,6 @@ LL | fn add(self) -> Foo<{ A::add(N) }> { = note: expected constant `false` found constant `true` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs index 85ca5fc904877..11f353f3f8ad3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -6,7 +6,9 @@ trait Bar {} trait Foo { fn a(); fn b() where Self: ~const Bar; + //~^ ERROR `~const` is not allowed here fn c(); + //~^ ERROR `~const` is not allowed here } fn test1() { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr index 255878e177528..3d6fedbabbf60 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -1,5 +1,29 @@ +error: `~const` is not allowed here + --> $DIR/trait-where-clause.rs:8:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/trait-where-clause.rs:8:8 + | +LL | fn b() where Self: ~const Bar; + | ^ + +error: `~const` is not allowed here + --> $DIR/trait-where-clause.rs:10:13 + | +LL | fn c(); + | ^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/trait-where-clause.rs:10:8 + | +LL | fn c(); + | ^ + error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:14:5 + --> $DIR/trait-where-clause.rs:16:5 | LL | T::b(); | ^ the trait `Bar` is not implemented for `T` @@ -15,13 +39,13 @@ LL | fn test1() { | +++++ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:16:12 + --> $DIR/trait-where-clause.rs:18:12 | LL | T::c::(); | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause.rs:9:13 + --> $DIR/trait-where-clause.rs:10:13 | LL | fn c(); | ^^^^^^^^^^ required by this bound in `Foo::c` @@ -30,6 +54,6 @@ help: consider further restricting this bound LL | fn test1() { | +++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr index 497ee440dfdb8..c0a322edcd647 100644 --- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr @@ -20,6 +20,7 @@ LL | let _: ::Bar = (); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-fully-qualified-paths.rs:25:13 diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr index 8769cbb35b0c4..041572be84411 100644 --- a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr +++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr @@ -29,6 +29,7 @@ LL | use foo::{bar::{XX, baz::{}}}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-nested-empty-paths.rs:27:5 @@ -47,6 +48,7 @@ LL | use foo::{bar::{baz::{}, baz1::{}}}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 previous errors diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-paths.stderr index 354a6fe32526c..4a70bb7e5c875 100644 --- a/tests/ui/rust-2018/edition-lint-nested-paths.stderr +++ b/tests/ui/rust-2018/edition-lint-nested-paths.stderr @@ -20,6 +20,7 @@ LL | use foo::{a, b}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-nested-paths.rs:23:13 @@ -38,6 +39,7 @@ LL | use foo::{self as x, c}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/rust-2018/edition-lint-paths.stderr b/tests/ui/rust-2018/edition-lint-paths.stderr index 42652be9401c3..fde17338d98a7 100644 --- a/tests/ui/rust-2018/edition-lint-paths.stderr +++ b/tests/ui/rust-2018/edition-lint-paths.stderr @@ -38,6 +38,7 @@ LL | use {main, Bar as SomethingElse}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-paths.rs:25:9 @@ -47,6 +48,7 @@ LL | use {main, Bar as SomethingElse}; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-paths.rs:40:5 diff --git a/tests/ui/rust-2018/trait-import-suggestions.rs b/tests/ui/rust-2018/trait-import-suggestions.rs index 9c67c3f4b4b2e..900b3d09334d0 100644 --- a/tests/ui/rust-2018/trait-import-suggestions.rs +++ b/tests/ui/rust-2018/trait-import-suggestions.rs @@ -1,6 +1,6 @@ // edition:2018 // aux-build:trait-import-suggestions.rs -// compile-flags:--extern trait-import-suggestions +// compile-flags:--extern trait_import_suggestions mod foo { mod foobar { diff --git a/tests/ui/rust-2018/uniform-paths/cross-crate.stderr b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr index 45f77a0c9fe6a..8682c56d2a5a7 100644 --- a/tests/ui/rust-2018/uniform-paths/cross-crate.stderr +++ b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr @@ -33,6 +33,7 @@ note: the tool module imported here | LL | use cross_crate::*; | ^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr index 908bb49858613..3dacb7969114f 100644 --- a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr @@ -51,6 +51,7 @@ note: the tool module imported here | LL | use rustfmt as imported_rustfmt; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot use a tool module through an import --> $DIR/prelude-fail-2.rs:19:13 @@ -63,6 +64,7 @@ note: the tool module imported here | LL | pub use rustfmt as imported_rustfmt; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/sanitize/cfg.rs b/tests/ui/sanitize/cfg.rs index f8ccf3b042dba..761c646ec884a 100644 --- a/tests/ui/sanitize/cfg.rs +++ b/tests/ui/sanitize/cfg.rs @@ -3,11 +3,12 @@ // check-pass // revisions: address cfi kcfi leak memory thread +//compile-flags: -Ctarget-feature=-crt-static //[address]needs-sanitizer-address //[address]compile-flags: -Zsanitizer=address --cfg address //[cfi]needs-sanitizer-cfi //[cfi]compile-flags: -Zsanitizer=cfi --cfg cfi -//[cfi]compile-flags: -Clto -Ccodegen-units=1 -Ctarget-feature=-crt-static +//[cfi]compile-flags: -Clto -Ccodegen-units=1 //[kcfi]needs-llvm-components: x86 //[kcfi]compile-flags: -Zsanitizer=kcfi --cfg kcfi --target x86_64-unknown-none //[leak]needs-sanitizer-leak diff --git a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr index 8328178e8d0ae..1006c3bc17efc 100644 --- a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr @@ -3,6 +3,8 @@ error: cfi sanitizer is not supported for this target error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi` error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr index 8328178e8d0ae..1006c3bc17efc 100644 --- a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr @@ -3,6 +3,8 @@ error: cfi sanitizer is not supported for this target error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi` error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed index ccd65ff409138..a400a1672a43c 100644 --- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed +++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed @@ -8,5 +8,6 @@ impl S { } fn main() { - Pin::new(&mut S).x(); //~ ERROR no method named `x` found + let mut pinned = std::pin::pin!(S); + pinned.as_mut().x(); //~ ERROR no method named `x` found } diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr index f34ce4dce490f..5dcb5861120a8 100644 --- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr +++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr @@ -4,16 +4,14 @@ error[E0599]: no method named `x` found for struct `S` in the current scope LL | struct S; | -------- method `x` not found for this struct ... -LL | fn x(self: Pin<&mut Self>) { - | - the method is available for `Pin<&mut S>` here -... LL | S.x(); | ^ method not found in `S` | -help: consider wrapping the receiver expression with the appropriate type +help: consider pinning the expression + | +LL ~ let mut pinned = std::pin::pin!(S); +LL ~ pinned.as_mut().x(); | -LL | Pin::new(&mut S).x(); - | +++++++++++++ + error: aborting due to previous error diff --git a/tests/ui/self/class-missing-self.stderr b/tests/ui/self/class-missing-self.stderr index 3c37d8197432c..ca7a896200fc3 100644 --- a/tests/ui/self/class-missing-self.stderr +++ b/tests/ui/self/class-missing-self.stderr @@ -2,7 +2,12 @@ error[E0425]: cannot find value `meows` in this scope --> $DIR/class-missing-self.rs:9:7 | LL | meows += 1; - | ^^^^^ help: you might have meant to use the available field: `self.meows` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.meows += 1; + | +++++ error[E0425]: cannot find function `sleep` in this scope --> $DIR/class-missing-self.rs:10:7 @@ -10,7 +15,7 @@ error[E0425]: cannot find function `sleep` in this scope LL | sleep(); | ^^^^^ not found in this scope | -help: consider using the associated function +help: consider using the method on `Self` | LL | self.sleep(); | +++++ diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index 0ff2203ec722e..6ba93e46f75e6 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -1,6 +1,7 @@ // build-fail -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics, rustc_attrs, adt_const_params)] +#![allow(incomplete_features)] #[repr(simd)] #[derive(Copy, Clone)] @@ -35,6 +36,7 @@ extern "platform-intrinsic" { fn simd_extract(x: T, idx: u32) -> E; fn simd_shuffle(x: T, y: T, idx: I) -> U; + fn simd_shuffle_generic(x: T, y: T) -> U; } fn main() { @@ -71,5 +73,29 @@ fn main() { //~^ ERROR expected return type of length 4, found `i32x8` with length 8 simd_shuffle::<_, _, i32x2>(x, x, IDX8); //~^ ERROR expected return type of length 8, found `i32x2` with length 2 + + const I2: &[u32] = &[0; 2]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const I4: &[u32] = &[0; 4]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const I8: &[u32] = &[0; 8]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + simd_shuffle_generic::<_, f32x2, I2>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + simd_shuffle_generic::<_, f32x4, I4>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + simd_shuffle_generic::<_, f32x8, I8>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + + simd_shuffle_generic::<_, i32x8, I2>(x, x); + //~^ ERROR expected return type of length 2, found `i32x8` with length 8 + simd_shuffle_generic::<_, i32x8, I4>(x, x); + //~^ ERROR expected return type of length 4, found `i32x8` with length 8 + simd_shuffle_generic::<_, i32x2, I8>(x, x); + //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } } diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index 115d9d4b3f3ac..26e01344939cc 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,75 +1,129 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:44:9 + --> $DIR/generic-elements.rs:46:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:48:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:50:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:52:9 + --> $DIR/generic-elements.rs:54:9 | LL | simd_shuffle::(0, 0, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:55:9 + --> $DIR/generic-elements.rs:57:9 | LL | simd_shuffle::(0, 0, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:58:9 + --> $DIR/generic-elements.rs:60:9 | LL | simd_shuffle::(0, 0, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:61:9 + --> $DIR/generic-elements.rs:63:9 | LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:63:9 + --> $DIR/generic-elements.rs:65:9 | LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:65:9 + --> $DIR/generic-elements.rs:67:9 | LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:68:9 + --> $DIR/generic-elements.rs:70:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:70:9 + --> $DIR/generic-elements.rs:72:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:72:9 + --> $DIR/generic-elements.rs:74:9 | LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:78:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:81:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:84:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + --> $DIR/generic-elements.rs:87:9 + | +LL | simd_shuffle_generic::<_, f32x2, I2>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + --> $DIR/generic-elements.rs:89:9 + | +LL | simd_shuffle_generic::<_, f32x4, I4>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + --> $DIR/generic-elements.rs:91:9 + | +LL | simd_shuffle_generic::<_, f32x8, I8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:94:9 + | +LL | simd_shuffle_generic::<_, i32x8, I2>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:96:9 + | +LL | simd_shuffle_generic::<_, i32x8, I4>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2 + --> $DIR/generic-elements.rs:98:9 + | +LL | simd_shuffle_generic::<_, i32x2, I8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr new file mode 100644 index 0000000000000..fc66b195674c6 --- /dev/null +++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr @@ -0,0 +1,12 @@ +error: overly complex generic constant + --> $DIR/monomorphize-shuffle-index.rs:29:45 + | +LL | return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); + | ^^--------^^ + | | + | pointer casts are not allowed in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: aborting due to previous error + diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index 2467baa08b0a7..db7953f06dd46 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -1,8 +1,14 @@ -//run-pass -#![feature(repr_simd, platform_intrinsics)] +//[old]run-pass +//[generic_with_fn]run-pass +// revisions: old generic generic_with_fn +#![feature(repr_simd, platform_intrinsics, adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] extern "platform-intrinsic" { + #[cfg(old)] fn simd_shuffle(a: T, b: T, i: I) -> U; + #[cfg(any(generic, generic_with_fn))] + fn simd_shuffle_generic(a: T, b: T) -> U; } #[derive(Copy, Clone)] @@ -11,12 +17,24 @@ struct Simd([T; N]); trait Shuffle { const I: [u32; N]; - - unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd { - simd_shuffle(a, b, Self::I) + const J: &'static [u32] = &Self::I; + + unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd + where + Thing<{ Self::J }>:, + { + #[cfg(old)] + return simd_shuffle(a, b, Self::I); + #[cfg(generic)] + return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); + //[generic]~^ overly complex generic constant + #[cfg(generic_with_fn)] + return simd_shuffle_generic::<_, _, { Self::J }>(a, b); } } +struct Thing; + fn main() { struct I1; impl Shuffle<4> for I1 { diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr index ba8da2e756040..29a606c4f0188 100644 --- a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -42,7 +42,7 @@ LL | f(Box::new(|a| { | --- captured by this `FnMut` closure LL | LL | foo(f); - | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58]`, which does not implement the `Copy` trait + | ^ move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr index 81211b20a0135..500080832111b 100644 --- a/tests/ui/span/issue-39698.stderr +++ b/tests/ui/span/issue-39698.stderr @@ -1,3 +1,13 @@ +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b` + | | | | + | | | pattern doesn't bind `b` + | | variable not in all patterns + | pattern doesn't bind `b` + error[E0408]: variable `c` is not bound in all patterns --> $DIR/issue-39698.rs:10:9 | @@ -8,16 +18,6 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | pattern doesn't bind `c` | pattern doesn't bind `c` -error[E0408]: variable `d` is not bound in all patterns - --> $DIR/issue-39698.rs:10:37 - | -LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } - | - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d` - | | | | - | | | pattern doesn't bind `d` - | | variable not in all patterns - | variable not in all patterns - error[E0408]: variable `a` is not bound in all patterns --> $DIR/issue-39698.rs:10:23 | @@ -28,15 +28,15 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | pattern doesn't bind `a` | variable not in all patterns -error[E0408]: variable `b` is not bound in all patterns - --> $DIR/issue-39698.rs:10:9 +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/issue-39698.rs:10:37 | LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } - | ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b` - | | | | - | | | pattern doesn't bind `b` - | | variable not in all patterns - | pattern doesn't bind `b` + | - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d` + | | | | + | | | pattern doesn't bind `d` + | | variable not in all patterns + | variable not in all patterns error: aborting due to 4 previous errors diff --git a/tests/ui/span/move-closure.stderr b/tests/ui/span/move-closure.stderr index dcc6078969449..2127b82020562 100644 --- a/tests/ui/span/move-closure.stderr +++ b/tests/ui/span/move-closure.stderr @@ -7,7 +7,7 @@ LL | let x: () = move || (); | expected due to this | = note: expected unit type `()` - found closure `[closure@$DIR/move-closure.rs:5:17: 5:24]` + found closure `{closure@$DIR/move-closure.rs:5:17: 5:24}` help: use parentheses to call this closure | LL | let x: () = (move || ())(); diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr index c263fe4672427..85aac16f6d036 100644 --- a/tests/ui/specialization/issue-52050.stderr +++ b/tests/ui/specialization/issue-52050.stderr @@ -11,11 +11,13 @@ LL | #![feature(specialization)] error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()` --> $DIR/issue-52050.rs:28:1 | -LL | impl IntoPyDictPointer for I - | ------------------------------- first implementation here +LL | / impl IntoPyDictPointer for I +LL | | where +LL | | I: Iterator, + | |________________- first implementation here ... -LL | impl IntoPyDictPointer for () - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` +LL | impl IntoPyDictPointer for () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.stderr index ecccf29a107dc..774ac9536175d 100644 --- a/tests/ui/specialization/specialization-default-types.stderr +++ b/tests/ui/specialization/specialization-default-types.stderr @@ -12,7 +12,7 @@ error[E0308]: mismatched types --> $DIR/specialization-default-types.rs:15:9 | LL | default type Output = Box; - | ----------------------------- expected this associated type + | ----------------------------- associated type is `default` and may be overridden LL | default fn generate(self) -> Self::Output { | ------------ expected `::Output` because of return type LL | Box::new(self) diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index d723ff538a886..813e65e45a255 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -146,33 +146,33 @@ hir-stats - Trait 192 ( 2.1%) 4 hir-stats WherePredicate 192 ( 2.1%) 3 64 hir-stats - BoundPredicate 192 ( 2.1%) 3 hir-stats Block 288 ( 3.2%) 6 48 -hir-stats Pat 360 ( 4.0%) 5 72 +hir-stats Pat 360 ( 3.9%) 5 72 hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Binding 216 ( 2.4%) 3 hir-stats GenericParam 400 ( 4.4%) 5 80 -hir-stats Generics 560 ( 6.2%) 10 56 -hir-stats Ty 720 ( 8.0%) 15 48 +hir-stats Generics 560 ( 6.1%) 10 56 +hir-stats Ty 720 ( 7.9%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 -hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.5%) 12 64 +hir-stats - Path 624 ( 6.8%) 13 +hir-stats Expr 768 ( 8.4%) 12 64 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Lit 128 ( 1.4%) 2 hir-stats - Block 384 ( 4.2%) 6 -hir-stats Item 880 ( 9.7%) 11 80 -hir-stats - Trait 80 ( 0.9%) 1 -hir-stats - Enum 80 ( 0.9%) 1 -hir-stats - ExternCrate 80 ( 0.9%) 1 -hir-stats - ForeignMod 80 ( 0.9%) 1 -hir-stats - Impl 80 ( 0.9%) 1 -hir-stats - Fn 160 ( 1.8%) 2 -hir-stats - Use 320 ( 3.5%) 4 -hir-stats Path 1_240 (13.7%) 31 40 -hir-stats PathSegment 1_920 (21.2%) 40 48 +hir-stats Item 968 (10.6%) 11 88 +hir-stats - Trait 88 ( 1.0%) 1 +hir-stats - Enum 88 ( 1.0%) 1 +hir-stats - ExternCrate 88 ( 1.0%) 1 +hir-stats - ForeignMod 88 ( 1.0%) 1 +hir-stats - Impl 88 ( 1.0%) 1 +hir-stats - Fn 176 ( 1.9%) 2 +hir-stats - Use 352 ( 3.9%) 4 +hir-stats Path 1_240 (13.6%) 31 40 +hir-stats PathSegment 1_920 (21.0%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 9_048 +hir-stats Total 9_136 hir-stats diff --git a/tests/ui/stats/meta-stats.rs b/tests/ui/stats/meta-stats.rs new file mode 100644 index 0000000000000..2d38e0882866d --- /dev/null +++ b/tests/ui/stats/meta-stats.rs @@ -0,0 +1,7 @@ +// build-pass +// dont-check-compiler-stderr +// compile-flags: -Zmeta-stats + +#![crate_type = "lib"] + +pub fn a() {} diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index cb1a6fcacfc9b..e8bbb8058faf3 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -7,7 +7,8 @@ LL | let _: u8 = s[4]; = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index<{integer}>` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -21,7 +22,8 @@ LL | let _ = s.get(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -36,7 +38,8 @@ LL | let _ = s.get_unchecked(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index ca4b86ba3065b..e6835bb54fb3d 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -31,7 +31,8 @@ LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -45,7 +46,8 @@ LL | s.get_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -60,7 +62,8 @@ LL | s.get_unchecked_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs index ee704198d193b..b3c323d2a29f5 100644 --- a/tests/ui/structs-enums/rec-align-u32.rs +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -3,7 +3,7 @@ #![allow(unused_unsafe)] // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem; diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index f21c9b2c808c5..de008bcc01d29 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -5,7 +5,7 @@ // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem; @@ -37,6 +37,7 @@ struct Outer { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "hurd", target_os = "illumos", target_os = "linux", target_os = "macos", diff --git a/tests/ui/suggestions/assoc-const-without-self.stderr b/tests/ui/suggestions/assoc-const-without-self.stderr index 88d72da70cb9b..05528d277be5b 100644 --- a/tests/ui/suggestions/assoc-const-without-self.stderr +++ b/tests/ui/suggestions/assoc-const-without-self.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find value `A_CONST` in this scope LL | A_CONST | ^^^^^^^ not found in this scope | -help: consider using the associated constant +help: consider using the associated constant on `Self` | LL | Self::A_CONST | ++++++ diff --git a/tests/ui/suggestions/assoc-type-in-method-return.stderr b/tests/ui/suggestions/assoc-type-in-method-return.stderr index 202e4a16eada7..df3828ad411e1 100644 --- a/tests/ui/suggestions/assoc-type-in-method-return.stderr +++ b/tests/ui/suggestions/assoc-type-in-method-return.stderr @@ -2,7 +2,12 @@ error[E0412]: cannot find type `Bla` in this scope --> $DIR/assoc-type-in-method-return.rs:3:25 | LL | fn to_bla(&self) -> Bla; - | ^^^ help: you might have meant to use the associated type: `Self::Bla` + | ^^^ + | +help: you might have meant to use the associated type + | +LL | fn to_bla(&self) -> Self::Bla; + | ++++++ error: aborting due to previous error diff --git a/tests/ui/suggestions/assoc_fn_without_self.rs b/tests/ui/suggestions/assoc_fn_without_self.rs index 778d9847773f3..35c16ef3e9f7c 100644 --- a/tests/ui/suggestions/assoc_fn_without_self.rs +++ b/tests/ui/suggestions/assoc_fn_without_self.rs @@ -17,4 +17,12 @@ impl S { bar(); //~ ERROR cannot find function `bar` in this scope baz(2, 3); //~ ERROR cannot find function `baz` in this scope } + fn d(&self) { + fn c() { + foo(); //~ ERROR cannot find function `foo` in this scope + } + foo(); //~ ERROR cannot find function `foo` in this scope + bar(); //~ ERROR cannot find function `bar` in this scope + baz(2, 3); //~ ERROR cannot find function `baz` in this scope + } } diff --git a/tests/ui/suggestions/assoc_fn_without_self.stderr b/tests/ui/suggestions/assoc_fn_without_self.stderr index febdd67338c99..9cee7c7ee5ee8 100644 --- a/tests/ui/suggestions/assoc_fn_without_self.stderr +++ b/tests/ui/suggestions/assoc_fn_without_self.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find function `foo` in this scope LL | foo(); | ^^^ not found in this scope | -help: consider using the associated function +help: consider using the associated function on `Self` | LL | Self::foo(); | ++++++ @@ -12,31 +12,68 @@ LL | Self::foo(); error[E0425]: cannot find function `bar` in this scope --> $DIR/assoc_fn_without_self.rs:17:9 | +LL | fn bar(&self) {} + | --- a method by that name is available on `Self` here +... +LL | bar(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/assoc_fn_without_self.rs:18:9 + | +LL | baz(2, 3); + | ^^^ not found in this scope + | +help: consider using the associated function on `Self` + | +LL | Self::baz(2, 3); + | ++++++ + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:14:13 + | +LL | foo(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:24:9 + | +LL | foo(); + | ^^^ not found in this scope + | +help: consider using the associated function on `Self` + | +LL | Self::foo(); + | ++++++ + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/assoc_fn_without_self.rs:25:9 + | LL | bar(); | ^^^ not found in this scope | -help: consider using the associated function +help: consider using the method on `Self` | LL | self.bar(); | +++++ error[E0425]: cannot find function `baz` in this scope - --> $DIR/assoc_fn_without_self.rs:18:9 + --> $DIR/assoc_fn_without_self.rs:26:9 | LL | baz(2, 3); | ^^^ not found in this scope | -help: consider using the associated function +help: consider using the associated function on `Self` | LL | Self::baz(2, 3); | ++++++ error[E0425]: cannot find function `foo` in this scope - --> $DIR/assoc_fn_without_self.rs:14:13 + --> $DIR/assoc_fn_without_self.rs:22:13 | LL | foo(); | ^^^ not found in this scope -error: aborting due to 4 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 8ed62f854f096..3065f83ea3d1b 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -18,16 +18,16 @@ help: use parentheses to call this function LL | bar(foo()); | ++ -error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future +error[E0277]: `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | LL | bar(async_closure); - | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future + | --- ^^^^^^^^^^^^^ `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` - = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for closure `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` + = note: {closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/tests/ui/suggestions/auxiliary/extern-issue-98562.rs b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs new file mode 100644 index 0000000000000..948e40549c6db --- /dev/null +++ b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs @@ -0,0 +1,26 @@ +pub trait TraitE { + type I3; +} + +pub trait TraitD { + type I3; +} + +pub trait TraitC { + type I1; + type I2; +} + +pub trait TraitB { + type Item; +} + +pub trait TraitA { + fn baz< + U: TraitC + TraitD + TraitE, + V: TraitD + >(_: U, _: V) -> Self + where + U: TraitB, + ::Item: Copy; +} diff --git a/tests/ui/suggestions/call-boxed.stderr b/tests/ui/suggestions/call-boxed.stderr index 9b31ee07cca7d..11823ff09d318 100644 --- a/tests/ui/suggestions/call-boxed.stderr +++ b/tests/ui/suggestions/call-boxed.stderr @@ -6,10 +6,10 @@ LL | let mut x = 1i32; LL | let y = Box::new(|| 1); | -- the found closure LL | x = y; - | ^ expected `i32`, found `Box<[closure@call-boxed.rs:3:22]>` + | ^ expected `i32`, found `Box<{closure@call-boxed.rs:3:22}>` | = note: expected type `i32` - found struct `Box<[closure@$DIR/call-boxed.rs:3:22: 3:24]>` + found struct `Box<{closure@$DIR/call-boxed.rs:3:22: 3:24}>` help: use parentheses to call this closure | LL | x = y(); diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 0232d4c8db694..5093448d2ca4c 100644 --- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -79,7 +79,7 @@ LL | | } | |_____^ expected `Pin>`, found `async` block | = note: expected struct `Pin + Send + 'static)>>` - found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]` + found `async` block `{async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6}` help: you need to pin and box this expression | LL ~ Box::pin(async { diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 955148315baef..75a3ae1a83e2f 100644 --- a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -16,11 +16,11 @@ help: use parentheses to call this function LL | bar(foo()); | ++ -error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied +error[E0277]: the trait bound `{closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21}: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 | LL | bar(closure); - | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` + | --- ^^^^^^^ the trait `T` is not implemented for closure `{closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21}` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr index a137db8cdee66..40bb87c8a4066 100644 --- a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -271,7 +271,7 @@ LL | let _: usize = closure; | expected due to this | = note: expected type `usize` - found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21]` + found closure `{closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21}` help: use parentheses to call this closure | LL | let _: usize = closure(); diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr index b476d61017f14..2c29cfa0b910f 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -26,9 +26,9 @@ error: lifetime may not live long enough --> $DIR/impl-trait-missing-lifetime.rs:16:69 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - | -------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` - | | - | return type `impl Future>` contains a lifetime `'1` + | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | return type `impl Future>` contains a lifetime `'1` error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr index 361483cc08db2..9f00de17484fb 100644 --- a/tests/ui/suggestions/issue-101623.stderr +++ b/tests/ui/suggestions/issue-101623.stderr @@ -7,7 +7,8 @@ LL | Trait::do_stuff({ fun(&mut *inner) }); | | the trait `Trait<'_>` is not implemented for `*mut ()` | required by a bound introduced by this call | - = help: the trait `Trait<'a>` is implemented for `()` + = help: the trait `Trait<'_>` is implemented for `()` + = help: for that trait implementation, expected `()`, found `*mut ()` error: aborting due to previous error diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index b99b1b0b9b3b6..ec62153b0a76f 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -37,6 +37,7 @@ LL | bar: Box, | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | bar: Box, @@ -50,6 +51,7 @@ LL | bar: Box, | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | bar: Box, @@ -63,6 +65,7 @@ LL | pub struct Foo { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | dyn pub struct Foo { @@ -76,6 +79,7 @@ LL | pub struct Foo { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | dyn pub struct Foo { @@ -89,6 +93,7 @@ LL | pub struct Foo { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: use `dyn` | LL | dyn pub struct Foo { diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr index baf6b1447e69d..5e471819b27b8 100644 --- a/tests/ui/suggestions/issue-83892.stderr +++ b/tests/ui/suggestions/issue-83892.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-83892.rs:9:15 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | match () { LL | () => func() | ^^^^^^ expected `()`, found `u8` diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index 4de9da89c9bc6..c8ce146cebf9a 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -31,11 +31,11 @@ LL + #[derive(Clone)] LL | struct S; | -error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned +error[E0277]: `{static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` cannot be unpinned --> $DIR/issue-84973-blacklist.rs:17:13 | LL | f_unpin(static || { yield; }); - | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` + | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/issue-98562.rs b/tests/ui/suggestions/issue-98562.rs new file mode 100644 index 0000000000000..de04050d59312 --- /dev/null +++ b/tests/ui/suggestions/issue-98562.rs @@ -0,0 +1,12 @@ +// aux-build:extern-issue-98562.rs + +extern crate extern_issue_98562; +use extern_issue_98562::TraitA; + +struct X; +impl TraitA for X { + //~^ ERROR not all trait items implemented +} +//~^ HELP implement the missing item: `fn baz + TraitD, V: TraitD>(_: U, _: V) -> Self where U: TraitE, U: TraitB, ::Item: Copy { todo!() }` + +fn main() {} diff --git a/tests/ui/suggestions/issue-98562.stderr b/tests/ui/suggestions/issue-98562.stderr new file mode 100644 index 0000000000000..7897fa441a24f --- /dev/null +++ b/tests/ui/suggestions/issue-98562.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `baz` + --> $DIR/issue-98562.rs:7:1 + | +LL | impl TraitA for X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `baz` in implementation + | + = help: implement the missing item: `fn baz + TraitD, V: TraitD>(_: U, _: V) -> Self where U: TraitE, U: TraitB, ::Item: Copy { todo!() }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/lifetimes/issue-105544.fixed b/tests/ui/suggestions/lifetimes/issue-105544.fixed index 47087eb474972..c92114e181254 100644 --- a/tests/ui/suggestions/lifetimes/issue-105544.fixed +++ b/tests/ui/suggestions/lifetimes/issue-105544.fixed @@ -2,7 +2,7 @@ #![allow(warnings)] -fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... +fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... //~^ HELP consider adding an explicit lifetime bound (d, p) //~^ ERROR the parameter type `impl Sized` may not live long enough @@ -10,19 +10,20 @@ fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the } fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ { -//~^ HELP consider adding an explicit lifetime bound... +//~^ NOTE the parameter type `impl Sized` must be valid for the lifetime `'b` as defined here... +//~| HELP consider adding an explicit lifetime bound (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds //~^ ERROR the parameter type `impl Sized` may not live long enough } -fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... +fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... //~^ HELP consider adding an explicit lifetime bound (d, p) //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds } -fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... //~^ HELP consider adding an explicit lifetime bound (d, p) //~^ ERROR the parameter type `T` may not live long enough @@ -30,12 +31,13 @@ fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE th } fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { -//~^ HELP consider adding an explicit lifetime bound... +//~^ NOTE the parameter type `T` must be valid for the lifetime `'b` as defined here... +//~| HELP consider adding an explicit lifetime bound (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds //~^ ERROR the parameter type `T` may not live long enough } -fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... //~^ HELP consider adding an explicit lifetime bound (d, p) //~^ ERROR the parameter type `T` may not live long enough diff --git a/tests/ui/suggestions/lifetimes/issue-105544.rs b/tests/ui/suggestions/lifetimes/issue-105544.rs index bd3bc1ef9bd2d..bbd0f097f8408 100644 --- a/tests/ui/suggestions/lifetimes/issue-105544.rs +++ b/tests/ui/suggestions/lifetimes/issue-105544.rs @@ -10,7 +10,8 @@ fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter ty } fn foo1<'b>(d: impl Sized, p: &'b mut ()) -> impl Sized + '_ { -//~^ HELP consider adding an explicit lifetime bound... +//~^ NOTE the parameter type `impl Sized` must be valid for the lifetime `'b` as defined here... +//~| HELP consider adding an explicit lifetime bound (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds //~^ ERROR the parameter type `impl Sized` may not live long enough } @@ -30,7 +31,8 @@ fn bar(d: T, p: & mut ()) -> impl Sized + '_ { //~ NOTE the parameter } fn bar1<'b, T : Sized>(d: T, p: &'b mut ()) -> impl Sized + '_ { -//~^ HELP consider adding an explicit lifetime bound... +//~^ NOTE the parameter type `T` must be valid for the lifetime `'b` as defined here... +//~| HELP consider adding an explicit lifetime bound (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds //~^ ERROR the parameter type `T` may not live long enough } diff --git a/tests/ui/suggestions/lifetimes/issue-105544.stderr b/tests/ui/suggestions/lifetimes/issue-105544.stderr index 08fe21b11b501..553643c0c3f70 100644 --- a/tests/ui/suggestions/lifetimes/issue-105544.stderr +++ b/tests/ui/suggestions/lifetimes/issue-105544.stderr @@ -1,108 +1,86 @@ error[E0311]: the parameter type `impl Sized` may not live long enough --> $DIR/issue-105544.rs:7:5 | -LL | (d, p) - | ^^^^^^ - | -note: the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... - --> $DIR/issue-105544.rs:5:26 - | LL | fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { - | ^^^^^^^ -note: ...so that the type `impl Sized` will meet its required lifetime bounds - --> $DIR/issue-105544.rs:7:5 - | + | ------- the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... +LL | LL | (d, p) - | ^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^ ...so that the type `impl Sized` will meet its required lifetime bounds | -LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { - | ++++ ++++ ++ +help: consider adding an explicit lifetime bound + | +LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + 'a { + | ++++ ++++ ++ ~~ error[E0309]: the parameter type `impl Sized` may not live long enough - --> $DIR/issue-105544.rs:14:5 + --> $DIR/issue-105544.rs:15:5 | +LL | fn foo1<'b>(d: impl Sized, p: &'b mut ()) -> impl Sized + '_ { + | -- the parameter type `impl Sized` must be valid for the lifetime `'b` as defined here... +... LL | (d, p) | ^^^^^^ ...so that the type `impl Sized` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ { | ++++ error[E0311]: the parameter type `impl Sized + 'a` may not live long enough - --> $DIR/issue-105544.rs:20:5 - | -LL | (d, p) - | ^^^^^^ - | -note: the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... - --> $DIR/issue-105544.rs:18:36 + --> $DIR/issue-105544.rs:21:5 | LL | fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ { - | ^^^^^^^ -note: ...so that the type `impl Sized + 'a` will meet its required lifetime bounds - --> $DIR/issue-105544.rs:20:5 - | + | ------- the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... +LL | LL | (d, p) - | ^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^ ...so that the type `impl Sized + 'a` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | -LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { - | +++ ++++ ++ +LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + 'b { + | +++ ++++ ++ ~~ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/issue-105544.rs:27:5 - | -LL | (d, p) - | ^^^^^^ - | -note: the parameter type `T` must be valid for the anonymous lifetime defined here... - --> $DIR/issue-105544.rs:25:28 + --> $DIR/issue-105544.rs:28:5 | LL | fn bar(d: T, p: & mut ()) -> impl Sized + '_ { - | ^^^^^^^^ -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/issue-105544.rs:27:5 - | + | -------- the parameter type `T` must be valid for the anonymous lifetime defined here... +LL | LL | (d, p) - | ^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | -LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { - | +++ ++++ ++ +LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + 'a { + | +++ ++++ ++ ~~ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/issue-105544.rs:34:5 + --> $DIR/issue-105544.rs:36:5 | +LL | fn bar1<'b, T : Sized>(d: T, p: &'b mut ()) -> impl Sized + '_ { + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... +... LL | (d, p) | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { | ++++ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/issue-105544.rs:40:5 - | -LL | (d, p) - | ^^^^^^ - | -note: the parameter type `T` must be valid for the anonymous lifetime defined here... - --> $DIR/issue-105544.rs:38:38 + --> $DIR/issue-105544.rs:42:5 | LL | fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ { - | ^^^^^^^ -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/issue-105544.rs:40:5 - | + | ------- the parameter type `T` must be valid for the anonymous lifetime defined here... +LL | LL | (d, p) - | ^^^^^^ -help: consider adding an explicit lifetime bound... + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound | -LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { - | +++ ++++ ++ +LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + 'b { + | +++ ++++ ++ ~~ error: aborting due to 6 previous errors diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed index 4013d98c3cfe7..474986283fc4f 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed @@ -19,11 +19,16 @@ trait Test { fn test(&self); } -fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) { +fn func<'a, T: Test + 'a>(_dummy: &Foo, foo: &Foo<'a>, t: T) { foo.bar(move |_| { //~^ ERROR the parameter type `T` may not live long enough t.test(); }); } +// Test that the suggested fix does not overconstrain `func`. See #115375. +fn test_func<'a, T: Test + 'a>(dummy: &Foo, foo: &Foo<'a>, t: T) { + func(dummy, foo, t); +} + fn main() {} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs index 4096d95e5fd7f..99c8e9626af7f 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs @@ -19,11 +19,16 @@ trait Test { fn test(&self); } -fn func(foo: &Foo, t: T) { +fn func(_dummy: &Foo, foo: &Foo, t: T) { foo.bar(move |_| { //~^ ERROR the parameter type `T` may not live long enough t.test(); }); } +// Test that the suggested fix does not overconstrain `func`. See #115375. +fn test_func<'a, T: Test + 'a>(dummy: &Foo, foo: &Foo<'a>, t: T) { + func(dummy, foo, t); +} + fn main() {} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 936d87f796824..6c63e1ada6138 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -1,29 +1,18 @@ error[E0311]: the parameter type `T` may not live long enough --> $DIR/missing-lifetimes-in-signature-2.rs:23:5 | +LL | fn func(_dummy: &Foo, foo: &Foo, t: T) { + | --- the parameter type `T` must be valid for the anonymous lifetime defined here... LL | / foo.bar(move |_| { LL | | LL | | t.test(); LL | | }); - | |______^ + | |______^ ...so that the type `T` will meet its required lifetime bounds | -note: the parameter type `T` must be valid for the anonymous lifetime defined here... - --> $DIR/missing-lifetimes-in-signature-2.rs:22:24 +help: consider adding an explicit lifetime bound | -LL | fn func(foo: &Foo, t: T) { - | ^^^ -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature-2.rs:23:5 - | -LL | / foo.bar(move |_| { -LL | | -LL | | t.test(); -LL | | }); - | |______^ -help: consider adding an explicit lifetime bound... - | -LL | fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) { - | +++ ++++ ++ ++++ +LL | fn func<'a, T: Test + 'a>(_dummy: &Foo, foo: &Foo<'a>, t: T) { + | +++ ++++ ++++ error: aborting due to previous error diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 93cfa60b5ab89..64af17c830e2e 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -12,7 +12,7 @@ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not ap LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() | ------ ------------- opaque type defined here | | - | hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here + | hidden type `{closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12}` captures the anonymous lifetime defined here ... LL | / move || { LL | | @@ -28,28 +28,18 @@ LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:30:5 | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ------ the parameter type `G` must be valid for the anonymous lifetime defined here... +... LL | / move || { LL | | LL | | *dest = g.get(); LL | | } - | |_____^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined here... - --> $DIR/missing-lifetimes-in-signature.rs:26:26 - | -LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ -note: ...so that the type `G` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:30:5 + | |_____^ ...so that the type `G` will meet its required lifetime bounds | -LL | / move || { -LL | | -LL | | *dest = g.get(); -LL | | } - | |_____^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | -LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ +LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a LL | where LL ~ G: Get + 'a, | @@ -57,85 +47,53 @@ LL ~ G: Get + 'a, error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:52:5 | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ------ the parameter type `G` must be valid for the anonymous lifetime defined here... +... LL | / move || { LL | | LL | | *dest = g.get(); LL | | } - | |_____^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined here... - --> $DIR/missing-lifetimes-in-signature.rs:48:34 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ -note: ...so that the type `G` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:52:5 + | |_____^ ...so that the type `G` will meet its required lifetime bounds | -LL | / move || { -LL | | -LL | | *dest = g.get(); -LL | | } - | |_____^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | -LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ - | +++ ++++ ++ +LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + 'b + | +++ ++++ ++ ~~ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:61:9 | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ------ the parameter type `G` must be valid for the anonymous lifetime defined here... LL | / move || { LL | | LL | | *dest = g.get(); LL | | } - | |_________^ + | |_________^ ...so that the type `G` will meet its required lifetime bounds | -note: the parameter type `G` must be valid for the anonymous lifetime defined here... - --> $DIR/missing-lifetimes-in-signature.rs:60:47 +help: consider adding an explicit lifetime bound | -LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^ -note: ...so that the type `G` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:61:9 - | -LL | / move || { -LL | | -LL | | *dest = g.get(); -LL | | } - | |_________^ -help: consider adding an explicit lifetime bound... - | -LL | fn qux<'c, 'b, G: Get + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + '_ { - | +++ ++++ ++ +LL | fn qux<'c, 'b, G: Get + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + 'c { + | +++ ++++ ++ ~~ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:73:5 | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ the parameter type `G` must be valid for the anonymous lifetime defined here... +... LL | / move || { LL | | LL | | LL | | *dest = g.get(); LL | | } - | |_____^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined here... - --> $DIR/missing-lifetimes-in-signature.rs:69:34 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^^^^^ -note: ...so that the type `G` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | |_____^ ...so that the type `G` will meet its required lifetime bounds | -LL | / move || { -LL | | -LL | | -LL | | *dest = g.get(); -LL | | } - | |_____^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | -LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + 'a - | +++ ++++ ++ +LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + 'b + 'a + | +++ ++++ ++ ~~ error[E0621]: explicit lifetime required in the type of `dest` --> $DIR/missing-lifetimes-in-signature.rs:73:5 @@ -153,13 +111,16 @@ LL | | } error[E0309]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:85:5 | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | -- the parameter type `G` must be valid for the lifetime `'a` as defined here... +... LL | / move || { LL | | LL | | *dest = g.get(); LL | | } | |_____^ ...so that the type `G` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | G: Get + 'a, | ++++ diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed new file mode 100644 index 0000000000000..470cc67b9736b --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed @@ -0,0 +1,47 @@ +// Make sure we suggest the bound `T: 'a` in the correct scope: +// trait, impl or associated fn. +// run-rustfix + +struct Inv<'a>(Option<*mut &'a u8>); + +fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {} + +trait Trait1<'a>: Sized where Self: 'a { + fn foo(self, lt: Inv<'a>) { + check_bound(self, lt) + //~^ ERROR parameter type `Self` may not live long enough + } +} + +trait Trait2: Sized { + fn foo<'a>(self, lt: Inv<'a>) where Self: 'a { + check_bound(self, lt) + //~^ ERROR parameter type `Self` may not live long enough + } +} + +trait Trait3 { + fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a { + check_bound(arg, lt) + //~^ ERROR parameter type `T` may not live long enough + } +} + +trait Trait4<'a> { + fn foo(arg: T, lt: Inv<'a>) { + check_bound(arg, lt) + //~^ ERROR parameter type `T` may not live long enough + } +} + +trait Trait5<'a> { + fn foo(self, _: Inv<'a>); +} +impl<'a, T: 'a> Trait5<'a> for T { + fn foo(self, lt: Inv<'a>) { + check_bound(self, lt); + //~^ ERROR parameter type `T` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs new file mode 100644 index 0000000000000..874788e13ef09 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs @@ -0,0 +1,47 @@ +// Make sure we suggest the bound `T: 'a` in the correct scope: +// trait, impl or associated fn. +// run-rustfix + +struct Inv<'a>(Option<*mut &'a u8>); + +fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {} + +trait Trait1<'a>: Sized { + fn foo(self, lt: Inv<'a>) { + check_bound(self, lt) + //~^ ERROR parameter type `Self` may not live long enough + } +} + +trait Trait2: Sized { + fn foo<'a>(self, lt: Inv<'a>) { + check_bound(self, lt) + //~^ ERROR parameter type `Self` may not live long enough + } +} + +trait Trait3 { + fn foo<'a>(arg: T, lt: Inv<'a>) { + check_bound(arg, lt) + //~^ ERROR parameter type `T` may not live long enough + } +} + +trait Trait4<'a> { + fn foo(arg: T, lt: Inv<'a>) { + check_bound(arg, lt) + //~^ ERROR parameter type `T` may not live long enough + } +} + +trait Trait5<'a> { + fn foo(self, _: Inv<'a>); +} +impl<'a, T> Trait5<'a> for T { + fn foo(self, lt: Inv<'a>) { + check_bound(self, lt); + //~^ ERROR parameter type `T` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr new file mode 100644 index 0000000000000..d3ca2cc116228 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr @@ -0,0 +1,71 @@ +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/type-param-bound-scope.rs:11:9 + | +LL | trait Trait1<'a>: Sized { + | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... +LL | fn foo(self, lt: Inv<'a>) { +LL | check_bound(self, lt) + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | trait Trait1<'a>: Sized where Self: 'a { + | ++++++++++++++ + +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/type-param-bound-scope.rs:18:9 + | +LL | fn foo<'a>(self, lt: Inv<'a>) { + | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... +LL | check_bound(self, lt) + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn foo<'a>(self, lt: Inv<'a>) where Self: 'a { + | ++++++++++++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/type-param-bound-scope.rs:25:9 + | +LL | fn foo<'a>(arg: T, lt: Inv<'a>) { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | check_bound(arg, lt) + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a { + | +++++++++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/type-param-bound-scope.rs:32:9 + | +LL | trait Trait4<'a> { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | fn foo(arg: T, lt: Inv<'a>) { +LL | check_bound(arg, lt) + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn foo(arg: T, lt: Inv<'a>) { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/type-param-bound-scope.rs:42:9 + | +LL | impl<'a, T> Trait5<'a> for T { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | fn foo(self, lt: Inv<'a>) { +LL | check_bound(self, lt); + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | impl<'a, T: 'a> Trait5<'a> for T { + | ++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.fixed b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.fixed new file mode 100644 index 0000000000000..e30c556457e53 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.fixed @@ -0,0 +1,52 @@ +// We want to suggest a bound `T: 'a` but `'a` is elided, +// run-rustfix +// edition: 2018 +#![allow(dead_code)] + +struct Inv<'a>(Option<*mut &'a u8>); + +fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {} + +struct Elided<'a, T = ()>(Inv<'a>, T); + +struct MyTy(X); + +impl<'a, X> MyTy> { + async fn foo(self, arg: A, _: &str) -> &str { + check_bound(arg, self.0 .0); + //~^ ERROR parameter type `A` may not live long enough + "" + } +} + +// Make sure the new lifetime name doesn't conflict with +// other early- or late-bound lifetimes in-scope. +impl<'a, A> MyTy<(A, &'a ())> { + async fn foo2<'b>( + arg: A, + lt: Inv<'b>, + ) -> ( + impl Into<&'b str> + Into<&'b str> + 'b, + impl Into>> + 'b, + impl Into>>, + ) where A: 'b { + check_bound(arg, lt); + //~^ ERROR parameter type `A` may not live long enough + ("", None, None) + } + + // same as above but there is a late-bound lifetime named `'b`. + async fn bar2<'c, 'b>(_dummy: &'a u8, arg: A, lt: Inv<'c>) where A: 'c { + check_bound(arg, lt); + //~^ ERROR parameter type `A` may not live long enough + } +} + +impl<'a, A: 'a> MyTy> { + async fn foo3(self) { + check_bound(self.0 .1, self.0 .0); + //~^ ERROR parameter type `A` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.rs b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.rs new file mode 100644 index 0000000000000..85f08808b731c --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.rs @@ -0,0 +1,52 @@ +// We want to suggest a bound `T: 'a` but `'a` is elided, +// run-rustfix +// edition: 2018 +#![allow(dead_code)] + +struct Inv<'a>(Option<*mut &'a u8>); + +fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {} + +struct Elided<'a, T = ()>(Inv<'a>, T); + +struct MyTy(X); + +impl MyTy> { + async fn foo(self, arg: A, _: &str) -> &str { + check_bound(arg, self.0 .0); + //~^ ERROR parameter type `A` may not live long enough + "" + } +} + +// Make sure the new lifetime name doesn't conflict with +// other early- or late-bound lifetimes in-scope. +impl<'a, A> MyTy<(A, &'a ())> { + async fn foo2( + arg: A, + lt: Inv<'_>, + ) -> ( + impl Into<&str> + Into<&'_ str> + '_, + impl Into> + '_, + impl Into>>, + ) { + check_bound(arg, lt); + //~^ ERROR parameter type `A` may not live long enough + ("", None, None) + } + + // same as above but there is a late-bound lifetime named `'b`. + async fn bar2<'b>(_dummy: &'a u8, arg: A, lt: Inv<'_>) { + check_bound(arg, lt); + //~^ ERROR parameter type `A` may not live long enough + } +} + +impl MyTy> { + async fn foo3(self) { + check_bound(self.0 .1, self.0 .0); + //~^ ERROR parameter type `A` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.stderr b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.stderr new file mode 100644 index 0000000000000..2f74a006b3b74 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/type-param-missing-lifetime.stderr @@ -0,0 +1,66 @@ +error[E0311]: the parameter type `A` may not live long enough + --> $DIR/type-param-missing-lifetime.rs:16:9 + | +LL | impl MyTy> { + | -- the parameter type `A` must be valid for the anonymous lifetime as defined here... +LL | async fn foo(self, arg: A, _: &str) -> &str { +LL | check_bound(arg, self.0 .0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL ~ impl<'a, X> MyTy> { +LL ~ async fn foo(self, arg: A, _: &str) -> &str { + | + +error[E0311]: the parameter type `A` may not live long enough + --> $DIR/type-param-missing-lifetime.rs:33:9 + | +LL | lt: Inv<'_>, + | ------- the parameter type `A` must be valid for the anonymous lifetime defined here... +... +LL | check_bound(arg, lt); + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL ~ async fn foo2<'b>( +LL | arg: A, +LL ~ lt: Inv<'b>, +LL | ) -> ( +LL ~ impl Into<&'b str> + Into<&'b str> + 'b, +LL ~ impl Into>> + 'b, +LL ~ impl Into>>, +LL ~ ) where A: 'b { + | + +error[E0311]: the parameter type `A` may not live long enough + --> $DIR/type-param-missing-lifetime.rs:40:9 + | +LL | async fn bar2<'b>(_dummy: &'a u8, arg: A, lt: Inv<'_>) { + | ------- the parameter type `A` must be valid for the anonymous lifetime defined here... +LL | check_bound(arg, lt); + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | async fn bar2<'c, 'b>(_dummy: &'a u8, arg: A, lt: Inv<'c>) where A: 'c { + | +++ ~~ +++++++++++ + +error[E0311]: the parameter type `A` may not live long enough + --> $DIR/type-param-missing-lifetime.rs:47:9 + | +LL | impl MyTy> { + | -- the parameter type `A` must be valid for the anonymous lifetime as defined here... +LL | async fn foo3(self) { +LL | check_bound(self.0 .1, self.0 .0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | impl<'a, A: 'a> MyTy> { + | +++ ++++ ~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr index 77fa956287816..84cb6e98553ee 100644 --- a/tests/ui/suggestions/missing-assoc-fn.stderr +++ b/tests/ui/suggestions/missing-assoc-fn.stderr @@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter` LL | impl FromIterator<()> for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation | - = help: implement the missing item: `fn from_iter(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = () { todo!() }` + = help: implement the missing item: `fn from_iter>(_: T) -> Self { todo!() }` error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index 21d2378382cba..fa4bc2fa79d7c 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -164,6 +164,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k` | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); @@ -182,6 +183,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k` | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); @@ -200,6 +202,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k` | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); @@ -218,6 +221,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k` | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); @@ -254,6 +258,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k` | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); @@ -272,6 +277,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k` | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); @@ -290,6 +296,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k` | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); @@ -308,6 +315,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k` | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add missing lifetime argument | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr index 8b856d8de7033..97c13200ac36b 100644 --- a/tests/ui/suggestions/return-closures.stderr +++ b/tests/ui/suggestions/return-closures.stderr @@ -2,25 +2,25 @@ error[E0308]: mismatched types --> $DIR/return-closures.rs:3:5 | LL | fn foo() { - | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` + | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` LL | LL | |x: &i32| 1i32 | ^^^^^^^^^^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/return-closures.rs:3:5: 3:14]` + found closure `{closure@$DIR/return-closures.rs:3:5: 3:14}` error[E0308]: mismatched types --> $DIR/return-closures.rs:9:5 | LL | fn bar(i: impl Sized) { - | - help: a return type might be missing here: `-> _` + | - help: a return type might be missing here: `-> _` LL | LL | || i | ^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/return-closures.rs:9:5: 9:7]` + found closure `{closure@$DIR/return-closures.rs:9:5: 9:7}` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr index 84ecd749b0dda..656f71eb8773e 100644 --- a/tests/ui/suggestions/slice-issue-87994.stderr +++ b/tests/ui/suggestions/slice-issue-87994.stderr @@ -1,4 +1,4 @@ -error[E0277]: the size for values of type `[i32]` cannot be known at compilation time +error[E0277]: `[i32]` is not an iterator --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { @@ -13,7 +13,7 @@ LL | for _ in &v[1..] { LL | for _ in &mut v[1..] { | ++++ -error[E0277]: `[i32]` is not an iterator +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { @@ -28,7 +28,7 @@ LL | for _ in &v[1..] { LL | for _ in &mut v[1..] { | ++++ -error[E0277]: the size for values of type `[K]` cannot be known at compilation time +error[E0277]: `[K]` is not an iterator --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { @@ -43,7 +43,7 @@ LL | for i2 in &v2[1..] { LL | for i2 in &mut v2[1..] { | ++++ -error[E0277]: `[K]` is not an iterator +error[E0277]: the size for values of type `[K]` cannot be known at compilation time --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr index 09553b93c45ef..80ad3f9e41bf2 100644 --- a/tests/ui/suggestions/sugg-else-for-closure.stderr +++ b/tests/ui/suggestions/sugg-else-for-closure.stderr @@ -7,8 +7,8 @@ LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); | arguments to this method are incorrect | = note: expected reference `&str` - found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` -help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed + found closure `{closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28}` +help: the return type of this call is `{closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28}` due to the type of the argument passed --> $DIR/sugg-else-for-closure.rs:6:14 | LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr index 9a4e9fef43c57..e5d5ecc0be276 100644 --- a/tests/ui/suggestions/suggest-box.stderr +++ b/tests/ui/suggestions/suggest-box.stderr @@ -11,7 +11,7 @@ LL | | }; | |_____^ expected `Box Result<(), ()>>`, found closure | = note: expected struct `Box Result<(), ()>>` - found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]` + found closure `{closure@$DIR/suggest-box.rs:4:47: 4:49}` = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html help: store this in the heap by calling `Box::new` | diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 147dc9234c598..adf01339972e5 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -5,7 +5,8 @@ LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` - = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` help: dereference this index | diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed index 589ee1a474ad6..4f2fd5ba6001b 100644 --- a/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -3,9 +3,10 @@ use std::fmt::Debug; fn foo(d: impl Debug + 'static) { -//~^ HELP consider adding an explicit lifetime bound... +//~^ HELP consider adding an explicit lifetime bound bar(d); //~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE the parameter type `impl Debug` must be valid for the static lifetime... //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds } diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.rs b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs index 9a87129fbf28a..a266e360edbad 100644 --- a/tests/ui/suggestions/suggest-impl-trait-lifetime.rs +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -3,9 +3,10 @@ use std::fmt::Debug; fn foo(d: impl Debug) { -//~^ HELP consider adding an explicit lifetime bound... +//~^ HELP consider adding an explicit lifetime bound bar(d); //~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE the parameter type `impl Debug` must be valid for the static lifetime... //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds } diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr index cf912f4aac201..1660db1aa83c7 100644 --- a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `impl Debug` may not live long enough --> $DIR/suggest-impl-trait-lifetime.rs:7:5 | LL | bar(d); - | ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds + | ^^^^^^ + | | + | the parameter type `impl Debug` must be valid for the static lifetime... + | ...so that the type `impl Debug` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn foo(d: impl Debug + 'static) { | +++++++++ diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed new file mode 100644 index 0000000000000..0a08383317f76 --- /dev/null +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed @@ -0,0 +1,14 @@ +// edition: 2021 +// run-rustfix + +#![allow(unused)] + +// Make sure we don't ICE when suggesting a return type +// for an async fn that has late-bound vars... + +async fn ice(_: &i32) -> bool { + true + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs index 459b94f943b50..5c8f185bd4b07 100644 --- a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs @@ -1,4 +1,7 @@ // edition: 2021 +// run-rustfix + +#![allow(unused)] // Make sure we don't ICE when suggesting a return type // for an async fn that has late-bound vars... diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr index bff864b222bff..352f6da3607bc 100644 --- a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/suggest-ret-on-async-w-late.rs:7:5 + --> $DIR/suggest-ret-on-async-w-late.rs:10:5 | LL | async fn ice(_: &i32) { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | true | ^^^^ expected `()`, found `bool` diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr index 24bedb5297b1f..19e9af14535dc 100644 --- a/tests/ui/suggestions/unnamable-types.stderr +++ b/tests/ui/suggestions/unnamable-types.stderr @@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const C: _ = || 42; | ^ not allowed in type signatures | -note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named +note: however, the inferred type `{closure@unnamable-types.rs:17:14}` cannot be named --> $DIR/unnamable-types.rs:17:14 | LL | const C: _ = || 42; @@ -31,7 +31,7 @@ error: missing type for `const` item LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; | ^ | -note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named +note: however, the inferred type `S<{closure@unnamable-types.rs:23:31}>` cannot be named --> $DIR/unnamable-types.rs:23:11 | LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; @@ -55,7 +55,7 @@ error: missing type for `const` item LL | const G = || -> i32 { yield 0; return 1; }; | ^ | -note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named +note: however, the inferred type `{generator@$DIR/unnamable-types.rs:37:11: 37:20}` cannot be named --> $DIR/unnamable-types.rs:37:11 | LL | const G = || -> i32 { yield 0; return 1; }; diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index c1cbefac828d6..61d27ec69f4d2 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE) +error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h6fc0c8d27b1a289f) +error: demangling(basic::main::h9308686d0228fa1d) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index 7dd68e6e3a8e2..eb65f3b58fff8 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::hab58a402db4ebf3a) +error: demangling(issue_60925::foo::Foo::foo::h84ab5dafbd2a1508) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr index 71fd5f1d44a8d..2045dc6a36e1a 100644 --- a/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr +++ b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr @@ -9,6 +9,8 @@ error: cannot find derive macro `rustfmt` in this scope | LL | #[derive(rustfmt)] | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find attribute `rustfmt` in this scope --> $DIR/tool-attributes-misplaced-1.rs:9:3 diff --git a/tests/ui/tool_lints.stderr b/tests/ui/tool_lints.stderr index d36cd193b15c2..f1d825caba159 100644 --- a/tests/ui/tool_lints.stderr +++ b/tests/ui/tool_lints.stderr @@ -13,6 +13,7 @@ LL | #[warn(foo::bar)] | ^^^ | = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/trait-bounds/impl-bound-with-references-error.stderr b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr index b114d295d7816..63280b8616fe5 100644 --- a/tests/ui/trait-bounds/impl-bound-with-references-error.stderr +++ b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr @@ -12,8 +12,11 @@ LL + use std::borrow::Cow; error[E0119]: conflicting implementations of trait `From` for type `LabelText` --> $DIR/impl-bound-with-references-error.rs:9:1 | -LL | impl From for LabelText - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / impl From for LabelText +LL | | +LL | | where +LL | | T: Into>, + | |_______________________________^ | = note: conflicting implementation in crate `core`: - impl From for T; diff --git a/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs b/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs new file mode 100644 index 0000000000000..6c3125a9fc5fd --- /dev/null +++ b/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs @@ -0,0 +1,21 @@ +// check-pass +trait Bar<'a> { + type Assoc: 'static; +} + +impl<'a> Bar<'a> for () { + type Assoc = (); +} + +struct ImplsStatic> { + d: &'static >::Assoc, +} + +fn caller(b: ImplsStatic<()>) +where + for<'a> (): Bar<'a> +{ + let _: &<() as Bar<'static>>::Assoc = b.d; +} + +fn main() {} diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr index e7e8a796796b3..30a3c40db95b3 100644 --- a/tests/ui/traits/coercion-generic-bad.stderr +++ b/tests/ui/traits/coercion-generic-bad.stderr @@ -5,6 +5,7 @@ LL | let s: Box> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` | = help: the trait `Trait<&'static str>` is implemented for `Struct` + = help: for that trait implementation, expected `&'static str`, found `isize` = note: required for the cast from `Box` to `Box>` error: aborting due to previous error diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr index 568b7e5a64af9..7e676c9da011f 100644 --- a/tests/ui/traits/copy-guessing.stderr +++ b/tests/ui/traits/copy-guessing.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Option` --> $DIR/copy-guessing.rs:20:9 | LL | let n = None; - | ^ + | ^ ---- type must be known at this point | help: consider giving `n` an explicit type, where the type for type parameter `T` is specified | diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs index 9a444be500c41..205b1173e079f 100644 --- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs @@ -14,7 +14,5 @@ impl Method for Thing { fn main() { let thing = Thing(true); - thing.method(42); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed + thing.method(42); //~ ERROR type annotations needed } diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr index 57b2587ae5ccd..2185c51e59d87 100644 --- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 - | -LL | thing.method(42); - | ^^^^^^ - | -help: try using a fully qualified path to specify the expected types - | -LL | as Method>::method(thing, 42); - | +++++++++++++++++++++++++++++++++++ ~ - error[E0283]: type annotations needed --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 | @@ -28,7 +17,6 @@ help: try using a fully qualified path to specify the expected types LL | as Method>::method(thing, 42); | +++++++++++++++++++++++++++++++++++ ~ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-33140-hack-boundaries.stderr b/tests/ui/traits/issue-33140-hack-boundaries.stderr index 80a502c6335e2..06e1dfd372751 100644 --- a/tests/ui/traits/issue-33140-hack-boundaries.stderr +++ b/tests/ui/traits/issue-33140-hack-boundaries.stderr @@ -60,7 +60,7 @@ error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn Send LL | impl Trait5 for dyn Send {} | ------------------------ first implementation here LL | impl Trait5 for dyn Send where u32: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` error: aborting due to 8 previous errors diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr index f8625f53b78fa..a5c258eb36e9f 100644 --- a/tests/ui/traits/issue-38404.stderr +++ b/tests/ui/traits/issue-38404.stderr @@ -25,6 +25,7 @@ LL | trait A: std::ops::Add + Sized {} | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter LL | trait B: A {} | - this trait cannot be made into an object... + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-59029-1.stderr b/tests/ui/traits/issue-59029-1.stderr index 203a89285306d..51354bcc54540 100644 --- a/tests/ui/traits/issue-59029-1.stderr +++ b/tests/ui/traits/issue-59029-1.stderr @@ -9,6 +9,8 @@ error[E0220]: associated type `Res` not found for `Self` | LL | trait MkSvc = Svc where Self::Res: Svc; | ^^^ there is a similarly named associated type `Res` in the trait `Svc` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs index f5be6cf21c1cc..2331dda91680c 100644 --- a/tests/ui/traits/issue-77982.rs +++ b/tests/ui/traits/issue-77982.rs @@ -1,3 +1,4 @@ +// ignore-windows different list of satisfying impls use std::collections::HashMap; fn what() { diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 33cc186ac0b1f..592cfd970c64a 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:8:10 + --> $DIR/issue-77982.rs:9:10 | LL | opts.get(opt.as_ref()); | ^^^ ------------ type must be known at this point @@ -18,7 +18,7 @@ LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:8:10 + --> $DIR/issue-77982.rs:9:10 | LL | opts.get(opt.as_ref()); | ^^^ ------ type must be known at this point @@ -35,25 +35,34 @@ help: consider specifying the generic argument LL | opts.get::(opt.as_ref()); | +++++ -error[E0282]: type annotations needed - --> $DIR/issue-77982.rs:13:59 +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:14:59 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); - | ^^^^ - | + | --- ^^^^ + | | + | type must be known at this point + | + = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate: + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; help: try using a fully qualified path to specify the expected types | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into(0u32))).collect(); | +++++++++++++++++++++++ ~ error[E0283]: type annotations needed for `Box` - --> $DIR/issue-77982.rs:36:9 + --> $DIR/issue-77982.rs:37:9 | LL | let _ = ().foo(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `(): Foo<'_, _>` found - --> $DIR/issue-77982.rs:29:1 + --> $DIR/issue-77982.rs:30:1 | LL | impl Foo<'static, u32> for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,13 +74,13 @@ LL | let _: Box = ().foo(); | ++++++++ error[E0283]: type annotations needed for `Box` - --> $DIR/issue-77982.rs:40:9 + --> $DIR/issue-77982.rs:41:9 | LL | let _ = (&()).bar(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `&(): Bar<'_, _>` found - --> $DIR/issue-77982.rs:32:1 + --> $DIR/issue-77982.rs:33:1 | LL | impl<'a> Bar<'static, u32> for &'a () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,5 +93,4 @@ LL | let _: Box = (&()).bar(); error: aborting due to 5 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr index c6fc7bb12c9b3..4593fa2c48570 100644 --- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -23,7 +23,7 @@ LL | impl> Iterator for IteratorOfWrapped { | | | unsatisfied trait bound introduced here = note: 256 redundant requirements hidden - = note: required for `IteratorOfWrapped<(), Map>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>` to implement `Iterator` + = note: required for `IteratorOfWrapped<(), Map>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>` to implement `Iterator` error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr index fb6eebbd254a2..29e87571561d8 100644 --- a/tests/ui/traits/issue-99875.stderr +++ b/tests/ui/traits/issue-99875.stderr @@ -16,11 +16,11 @@ help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, LL | takes(function as fn(Argument) -> Return); | +++++++++++++++++++++++++ -error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied +error[E0277]: the trait bound `{closure@$DIR/issue-99875.rs:14:11: 14:34}: Trait` is not satisfied --> $DIR/issue-99875.rs:14:11 | LL | takes(|_: Argument| -> Return { todo!() }); - | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]` + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `{closure@$DIR/issue-99875.rs:14:11: 14:34}` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.rs b/tests/ui/traits/multidispatch-convert-ambig-dest.rs index aa74e11c36256..36e1e868fca13 100644 --- a/tests/ui/traits/multidispatch-convert-ambig-dest.rs +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.rs @@ -25,7 +25,6 @@ where T : Convert fn a() { test(22, std::default::Default::default()); //~^ ERROR type annotations needed - //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr index e927f26e96dd9..e3bfc78bb08d5 100644 --- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 - | -LL | test(22, std::default::Default::default()); - | ^^^^ cannot infer type of the type parameter `U` declared on the function `test` - | -help: consider specifying the generic arguments - | -LL | test::(22, std::default::Default::default()); - | ++++++++++ - error[E0283]: type annotations needed --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 | @@ -37,7 +26,6 @@ help: consider specifying the generic arguments LL | test::(22, std::default::Default::default()); | ++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 38d83d289f1e2..825e874d71bcb 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -27,6 +27,5 @@ fn main() { //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` - //~| ERROR type annotations needed println!("{x}"); } diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index abc6677c1323a..ca4b5c90ff280 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -11,18 +11,7 @@ note: required by a bound in `Foo::Item` LL | type Item: Copy | ^^^^ required by this bound in `Foo::Item` -error[E0282]: type annotations needed - --> $DIR/alias-bound-unsound.rs:24:5 - | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^ cannot infer type of the type parameter `T` declared on the function `drop` - | -help: consider specifying the generic argument - | -LL | drop::(<() as Foo>::copy_me(&x)); - | +++++ - -error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` +error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item` --> $DIR/alias-bound-unsound.rs:24:31 | LL | drop(<() as Foo>::copy_me(&x)); @@ -30,40 +19,39 @@ LL | drop(<() as Foo>::copy_me(&x)); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item` - --> $DIR/alias-bound-unsound.rs:24:31 +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); - | ^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized` --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) + = note: the return type of a function must have a statically known size -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:24:10 +error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` + --> $DIR/alias-bound-unsound.rs:24:31 | LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed` --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) - = note: the return type of a function must have a statically known size -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0275, E0282. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr index 8eda64e4490b4..46677a583160d 100644 --- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr +++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr @@ -5,6 +5,8 @@ LL | impl Overlaps> for ::Assoc {} | --------------------------------------------------------- first implementation here LL | impl Overlaps for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as TraitB>::Assoc` + | + = note: downstream crates may implement trait `TraitB` for type `std::boxed::Box<_>` error: aborting due to previous error diff --git a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr index 47004821ad7c6..414deb47727e3 100644 --- a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr +++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr @@ -1,9 +1,16 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/runaway-impl-candidate-selection.rs:13:22 | LL | println!("{:?}", iter::<_>()); | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter` + | + = note: cannot satisfy `_: Iterator` +note: required by a bound in `iter` + --> $DIR/runaway-impl-candidate-selection.rs:8:12 + | +LL | fn iter() -> ::Item { + | ^^^^^^^^ required by this bound in `iter` error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/async.fail.stderr b/tests/ui/traits/new-solver/async.fail.stderr index 72fa2eb31613d..44097b556fc11 100644 --- a/tests/ui/traits/new-solver/async.fail.stderr +++ b/tests/ui/traits/new-solver/async.fail.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[async block@$DIR/async.rs:12:17: 12:25] as Future>::Output == i32` +error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:25} as Future>::Output == i32` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs index e311a4af2f4ea..6b54718e35c92 100644 --- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs @@ -1,4 +1,4 @@ -// compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir +// compile-flags: -Ztrait-solver=next // edition: 2021 // revisions: pass fail //[pass] check-pass diff --git a/tests/ui/traits/new-solver/coherence/issue-102048.stderr b/tests/ui/traits/new-solver/coherence/issue-102048.stderr index 17a43838fe275..41bf68a1d9f39 100644 --- a/tests/ui/traits/new-solver/coherence/issue-102048.stderr +++ b/tests/ui/traits/new-solver/coherence/issue-102048.stderr @@ -1,11 +1,15 @@ error[E0119]: conflicting implementations of trait `Trait fn(<_ as WithAssoc1<'a>>::Assoc, <_ as WithAssoc2<'a>>::Assoc)>` for type `(_, _)` --> $DIR/issue-102048.rs:39:1 | -LL | impl Trait fn(>::Assoc, >::Assoc)> for (T, U) - | --------------------------------------------------------------------------------------------------- first implementation here +LL | / impl Trait fn(>::Assoc, >::Assoc)> for (T, U) +LL | | where +LL | | T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>, +LL | | U: for<'a> WithAssoc2<'a>, + | |______________________________- first implementation here ... -LL | impl Trait fn(>::Assoc, u32)> for (T, U) where - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)` +LL | / impl Trait fn(>::Assoc, u32)> for (T, U) where +LL | | U: for<'a> WithAssoc1<'a> + | |_____________________________^ conflicting implementation for `(_, _)` error: aborting due to previous error diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index 5d5f325e4b473..73d46c4df9602 100644 --- a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,3 +1,7 @@ +WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> +WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> +WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> +WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> error[E0119]: conflicting implementations of trait `Trait` for type `::Assoc` --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 | @@ -6,6 +10,8 @@ LL | impl Trait for T {} LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `::Assoc` + | + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `::Assoc` in future versions error: aborting due to previous error diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs index fcafdcf637a80..44e763ef9907d 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs @@ -27,6 +27,5 @@ fn impls() {} fn main() { impls::>(); - //~^ ERROR type annotations needed - //~| ERROR overflow evaluating the requirement + //~^ ERROR overflow evaluating the requirement } diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index a861156711d01..1ac0e297729ce 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -1,9 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/fixpoint-exponential-growth.rs:29:5 - | -LL | impls::>(); - | ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls` - error[E0275]: overflow evaluating the requirement `W<_>: Trait` --> $DIR/fixpoint-exponential-growth.rs:29:13 | @@ -17,7 +11,6 @@ note: required by a bound in `impls` LL | fn impls() {} | ^^^^^ required by this bound in `impls` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0275, E0282. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs new file mode 100644 index 0000000000000..2790639234060 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs @@ -0,0 +1,53 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs)] + +// Check that we correctly rerun the trait solver for heads of cycles, +// even if they are not the root. + +struct A(*const T); +struct B(*const T); +struct C(*const T); + +#[rustc_coinductive] +trait Trait<'a, 'b> {} +trait NotImplemented {} + +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for A where B: Trait<'a, 'b> {} + +// With this the root of `B` is `A`, even if the other impl does +// not have a cycle with `A`. This candidate never applies because of +// the `A: NotImplemented` bound. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B +where + A: Trait<'a, 'b>, + A: NotImplemented, +{ +} + +// This impl directly requires 'b to be equal to 'static. +// +// Because of the coinductive cycle through `C` it also requires +// 'a to be 'static. +impl<'a, T: ?Sized> Trait<'a, 'static> for B +where + C: Trait<'a, 'a>, +{} + +// In the first iteration of `B: Trait<'a, 'b>` we don't add any +// constraints here, only after setting the provisional result to require +// `'b == 'static` do we also add that constraint for `'a`. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for C +where + B: Trait<'a, 'b>, +{} + +fn impls_trait<'a, 'b, T: Trait<'a, 'b> + ?Sized>() {} + +fn check<'a, T: ?Sized>() { + impls_trait::<'a, 'static, A>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { + check::<()>(); +} diff --git a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr new file mode 100644 index 0000000000000..4cbd0898148a5 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:47:5 + | +LL | fn check<'a, T: ?Sized>() { + | -- lifetime `'a` defined here +LL | impls_trait::<'a, 'static, A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs index 3cfe7ab87f60a..f06b98a79cfe3 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs @@ -39,7 +39,7 @@ fn impls_ar() {} fn main() { impls_a::<()>(); - // FIXME(-Ztrait-solver=next): This is broken and should error. + //~^ ERROR overflow evaluating the requirement `(): A` impls_ar::<()>(); //~^ ERROR overflow evaluating the requirement `(): AR` diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr index 341153340635e..859b3f3f1c7d7 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr @@ -1,3 +1,16 @@ +error[E0275]: overflow evaluating the requirement `(): A` + --> $DIR/inductive-not-on-stack.rs:41:15 + | +LL | impls_a::<()>(); + | ^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_not_on_stack`) +note: required by a bound in `impls_a` + --> $DIR/inductive-not-on-stack.rs:25:15 + | +LL | fn impls_a() {} + | ^ required by this bound in `impls_a` + error[E0275]: overflow evaluating the requirement `(): AR` --> $DIR/inductive-not-on-stack.rs:44:16 | @@ -11,6 +24,6 @@ note: required by a bound in `impls_ar` LL | fn impls_ar() {} | ^^ required by this bound in `impls_ar` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/dont-ice-on-assoc-projection.stderr b/tests/ui/traits/new-solver/dont-ice-on-assoc-projection.stderr index 7ad495a35e0df..368f5cd0c3b1a 100644 --- a/tests/ui/traits/new-solver/dont-ice-on-assoc-projection.stderr +++ b/tests/ui/traits/new-solver/dont-ice-on-assoc-projection.stderr @@ -13,7 +13,7 @@ error[E0119]: conflicting implementations of trait `Foo` for type `()` LL | impl Foo for () {} | --------------- first implementation here LL | impl Foo for T where T: Bar {} - | ^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr index 9a8060133b819..9aa4f4531f95d 100644 --- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr @@ -1,9 +1,18 @@ -error[E0282]: type annotations needed +error[E0284]: type annotations needed: cannot satisfy `<>::Assoc as Id>::Assoc == <>::Assoc as Id>::Assoc` --> $DIR/generalize-proj-new-universe-index-2.rs:74:5 | LL | bound::<::Assoc, as Id>::Assoc, _>() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<>::Assoc as Id>::Assoc == <>::Assoc as Id>::Assoc` + | +note: required by a bound in `bound` + --> $DIR/generalize-proj-new-universe-index-2.rs:69:21 + | +LL | fn bound() + | ----- required by a bound in this function +LL | where +LL | T: WithAssoc, + | ^^^^^^^^^ required by this bound in `bound` error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/new-solver/generator.fail.stderr b/tests/ui/traits/new-solver/generator.fail.stderr index d94d41e3587b6..e3fe4bf5a6acf 100644 --- a/tests/ui/traits/new-solver/generator.fail.stderr +++ b/tests/ui/traits/new-solver/generator.fail.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `[generator@$DIR/generator.rs:18:21: 18:23]: Generator` is not satisfied +error[E0277]: the trait bound `{generator@$DIR/generator.rs:18:21: 18:23}: Generator` is not satisfied --> $DIR/generator.rs:18:21 | LL | needs_generator(|| { @@ -10,7 +10,7 @@ LL | | LL | | LL | | yield (); LL | | }); - | |_____^ the trait `Generator` is not implemented for `[generator@$DIR/generator.rs:18:21: 18:23]` + | |_____^ the trait `Generator` is not implemented for `{generator@$DIR/generator.rs:18:21: 18:23}` | note: required by a bound in `needs_generator` --> $DIR/generator.rs:14:28 @@ -18,7 +18,7 @@ note: required by a bound in `needs_generator` LL | fn needs_generator(_: impl Generator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_generator` -error[E0271]: type mismatch resolving `<[generator@$DIR/generator.rs:18:21: 18:23] as Generator>::Yield == B` +error[E0271]: type mismatch resolving `<{generator@$DIR/generator.rs:18:21: 18:23} as Generator>::Yield == B` --> $DIR/generator.rs:18:21 | LL | needs_generator(|| { @@ -38,7 +38,7 @@ note: required by a bound in `needs_generator` LL | fn needs_generator(_: impl Generator) {} | ^^^^^^^^^ required by this bound in `needs_generator` -error[E0271]: type mismatch resolving `<[generator@$DIR/generator.rs:18:21: 18:23] as Generator>::Return == C` +error[E0271]: type mismatch resolving `<{generator@$DIR/generator.rs:18:21: 18:23} as Generator>::Return == C` --> $DIR/generator.rs:18:21 | LL | needs_generator(|| { diff --git a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr index 0628320126104..f482e8cfaf966 100644 --- a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr +++ b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr @@ -1,9 +1,17 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5 | LL | foo(unconstrained()) - | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | ^^^ --------------- type must be known at this point + | | + | cannot infer type of the type parameter `T` declared on the function `foo` | + = note: cannot satisfy `_: Trait` +note: required by a bound in `foo` + --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:19:11 + | +LL | fn foo>(x: T) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` help: consider specifying the generic argument | LL | foo::(unconstrained()) @@ -11,4 +19,4 @@ LL | foo::(unconstrained()) error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs index b37f09ee185e9..3d2e70a639f50 100644 --- a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs +++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs @@ -15,6 +15,5 @@ fn impls() {} fn main() { impls::>(); - //~^ ERROR type annotations needed - //~| ERROR overflow evaluating the requirement `W<_>: Trait` + //~^ ERROR overflow evaluating the requirement `W<_>: Trait` } diff --git a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr index beed40f364958..023efc41aeb38 100644 --- a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr +++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr @@ -1,9 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/exponential-trait-goals.rs:17:5 - | -LL | impls::>(); - | ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls` - error[E0275]: overflow evaluating the requirement `W<_>: Trait` --> $DIR/exponential-trait-goals.rs:17:13 | @@ -17,7 +11,6 @@ note: required by a bound in `impls` LL | fn impls() {} | ^^^^^ required by this bound in `impls` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0275, E0282. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr index ed9b57cb1bd59..d8db07277c500 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -23,13 +23,13 @@ LL | where LL | for V: Sized, | ^^^^^ required by this bound in `foo` -error[E0277]: the size for values of type `V` cannot be known at compilation time +error[E0277]: `V` is not an iterator --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ doesn't have a size known at compile-time + | ^^^ `V` is not an iterator | - = help: the trait `Sized` is not implemented for `V` + = help: the trait `Iterator` is not implemented for `V` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 @@ -40,13 +40,13 @@ LL | where LL | for V: IntoIterator, | ^^^^^^^^^^^^ required by this bound in `bar` -error[E0277]: `V` is not an iterator +error[E0277]: the size for values of type `V` cannot be known at compilation time --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ `V` is not an iterator + | ^^^ doesn't have a size known at compile-time | - = help: the trait `Iterator` is not implemented for `V` + = help: the trait `Sized` is not implemented for `V` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.rs b/tests/ui/traits/non_lifetime_binders/on-rpit.rs new file mode 100644 index 0000000000000..c501e057e2830 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-rpit.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait {} + +impl Trait for i32 {} + +fn produce() -> impl for Trait { + 16 +} + +fn main() { + let _ = produce(); +} diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr new file mode 100644 index 0000000000000..34c56068c5cc5 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/on-rpit.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs index 538e74ee1b00f..e9e2f6b129017 100644 --- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs @@ -18,7 +18,5 @@ where fn main() { let a = A(B); - a.method(); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed + a.method(); //~ ERROR type annotations needed } diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr index 92d9d32cf9c70..86ae49b32fcf0 100644 --- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 - | -LL | a.method(); - | ^^^^^^ - | -help: try using a fully qualified path to specify the expected types - | -LL | as V>::method(a); - | +++++++++++++++++++++++ ~ - error[E0283]: type annotations needed --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 | @@ -35,7 +24,6 @@ help: try using a fully qualified path to specify the expected types LL | as V>::method(a); | +++++++++++++++++++++++ ~ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/suggest-fully-qualified-closure.rs b/tests/ui/traits/suggest-fully-qualified-closure.rs index c077921c0bdd2..6bbb6a95d7d59 100644 --- a/tests/ui/traits/suggest-fully-qualified-closure.rs +++ b/tests/ui/traits/suggest-fully-qualified-closure.rs @@ -1,6 +1,6 @@ // check-fail // known-bug: #103705 -// normalize-stderr-test "\[closure@.*\]" -> "[closure@]" +// normalize-stderr-test "\{closure@.*\}" -> "{closure@}" // normalize-stderr-test "\+* ~" -> "+++ ~" // The output of this currently suggests writing a closure in the qualified path. diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr index 3df623c14c3d6..43cef7027a2c6 100644 --- a/tests/ui/traits/suggest-fully-qualified-closure.stderr +++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/suggest-fully-qualified-closure.rs:23:7 - | -LL | q.lol(||()); - | ^^^ - | -help: try using a fully qualified path to specify the expected types - | -LL | >::lol::<[closure@]>(&q, ||()); - | +++ ~ - error[E0283]: type annotations needed --> $DIR/suggest-fully-qualified-closure.rs:23:7 | @@ -25,10 +14,9 @@ LL | impl MyTrait for Qqq{ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using a fully qualified path to specify the expected types | -LL | >::lol::<[closure@]>(&q, ||()); +LL | >::lol::<{closure@}>(&q, ||()); | +++ ~ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs index 9a2cf469d08e4..f0861857bf79f 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs @@ -42,9 +42,7 @@ impl DerefMut for DerefsTo { fn main() { let mut thing = Thing; - thing.method(); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed + thing.method(); //~ ERROR type annotations needed thing.mut_method(); //~ ERROR type annotations needed thing.by_self(); //~ ERROR type annotations needed diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr index 68b31a1ca34e3..841acb5ffd3cd 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 - | -LL | thing.method(); - | ^^^^^^ - | -help: try using a fully qualified path to specify the expected types - | -LL | >::method(&thing); - | ++++++++++++++++++++++++++++++ ~ - error[E0283]: type annotations needed --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 | @@ -29,7 +18,7 @@ LL | >::method(&thing); | ++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:46:11 | LL | thing.mut_method(); | ^^^^^^^^^^ @@ -48,7 +37,7 @@ LL | >::mut_method(&mut thing); | +++++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:47:11 | LL | thing.by_self(); | ^^^^^^^ @@ -67,7 +56,7 @@ LL | <&Thing as MethodRef>::by_self(&thing); | +++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:50:14 | LL | deref_to.method(); | ^^^^^^ @@ -86,7 +75,7 @@ LL | >::method(&deref_to); | ++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:51:14 | LL | deref_to.mut_method(); | ^^^^^^^^^^ @@ -105,7 +94,7 @@ LL | >::mut_method(&mut deref_to); | +++++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14 | LL | deref_to.by_self(); | ^^^^^^^ @@ -124,7 +113,7 @@ LL | <&Thing as MethodRef>::by_self(&deref_to); | +++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:55:20 | LL | deref_deref_to.method(); | ^^^^^^ @@ -143,7 +132,7 @@ LL | >::method(&deref_deref_to); | ++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:56:20 | LL | deref_deref_to.mut_method(); | ^^^^^^^^^^ @@ -162,7 +151,7 @@ LL | >::mut_method(&mut deref_deref_to); | +++++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20 + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20 | LL | deref_deref_to.by_self(); | ^^^^^^^ @@ -180,7 +169,6 @@ help: try using a fully qualified path to specify the expected types LL | <&Thing as MethodRef>::by_self(&deref_deref_to); | +++++++++++++++++++++++++++++++++++ ~ -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs index da640c8c8c26a..6a63e27f75ff9 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs @@ -42,9 +42,7 @@ impl DerefMut for DerefsTo { fn main() { let mut ref_thing = &Thing; - ref_thing.method(); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed + ref_thing.method(); //~ ERROR type annotations needed ref_thing.by_self(); //~ ERROR type annotations needed let mut mut_thing = &mut Thing; diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr index 27518a54e7507..1865d81bad19c 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr @@ -1,14 +1,3 @@ -error[E0282]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 - | -LL | ref_thing.method(); - | ^^^^^^ - | -help: try using a fully qualified path to specify the expected types - | -LL | >::method(ref_thing); - | +++++++++++++++++++++++++++++ ~ - error[E0283]: type annotations needed --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 | @@ -29,7 +18,7 @@ LL | >::method(ref_thing); | +++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:46:15 | LL | ref_thing.by_self(); | ^^^^^^^ @@ -48,7 +37,7 @@ LL | <&Thing as MethodRef>::by_self(ref_thing); | ++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:49:15 | LL | mut_thing.method(); | ^^^^^^ @@ -67,7 +56,7 @@ LL | >::method(mut_thing); | +++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:50:15 | LL | mut_thing.mut_method(); | ^^^^^^^^^^ @@ -86,7 +75,7 @@ LL | >::mut_method(mut_thing); | +++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15 | LL | mut_thing.by_self(); | ^^^^^^^ @@ -105,7 +94,7 @@ LL | <&Thing as MethodRef>::by_self(mut_thing); | ++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:54:14 | LL | deref_to.method(); | ^^^^^^ @@ -124,7 +113,7 @@ LL | >::method(deref_to); | +++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:55:14 | LL | deref_to.mut_method(); | ^^^^^^^^^^ @@ -143,7 +132,7 @@ LL | >::mut_method(deref_to); | +++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14 | LL | deref_to.by_self(); | ^^^^^^^ @@ -162,7 +151,7 @@ LL | <&Thing as MethodRef>::by_self(deref_to); | ++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:59:20 | LL | deref_deref_to.method(); | ^^^^^^ @@ -181,7 +170,7 @@ LL | >::method(deref_deref_to); | +++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:60:20 | LL | deref_deref_to.mut_method(); | ^^^^^^^^^^ @@ -200,7 +189,7 @@ LL | >::mut_method(deref_deref_to); | +++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20 + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20 | LL | deref_deref_to.by_self(); | ^^^^^^^ @@ -218,7 +207,6 @@ help: try using a fully qualified path to specify the expected types LL | <&Thing as MethodRef>::by_self(deref_deref_to); | ++++++++++++++++++++++++++++++++++ ~ -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/unsend-future.rs b/tests/ui/traits/unsend-future.rs index fbbc07b11e743..a8367573fbdfa 100644 --- a/tests/ui/traits/unsend-future.rs +++ b/tests/ui/traits/unsend-future.rs @@ -13,6 +13,7 @@ fn require_handler(h: H) {} async fn handler() { let a = &1 as *const i32; async {}.await; + let b = a; } fn main() { diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr index 6ce1cf452f459..01829021b4a79 100644 --- a/tests/ui/traits/unsend-future.stderr +++ b/tests/ui/traits/unsend-future.stderr @@ -1,5 +1,5 @@ error: future cannot be sent between threads safely - --> $DIR/unsend-future.rs:19:21 + --> $DIR/unsend-future.rs:20:21 | LL | require_handler(handler) | ^^^^^^^ future returned by `handler` is not `Send` @@ -12,8 +12,6 @@ LL | let a = &1 as *const i32; | - has type `*const i32` which is not `Send` LL | async {}.await; | ^^^^^ await occurs here, with `a` maybe used later -LL | } - | - `a` is later dropped here note: required by a bound in `require_handler` --> $DIR/unsend-future.rs:11:23 | diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index e11c3f810035c..b41bf86d3d911 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -6,6 +6,7 @@ LL | Err("")?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the trait `From` is implemented for `TryFromSliceError` + = help: for that trait implementation, expected `Infallible`, found `&str` = note: required for `Result` to implement `FromResidual>` error[E0271]: type mismatch resolving ` as Try>::Output == &str` diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 7eb392faa66b3..d8b9431becc6b 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -73,7 +73,8 @@ LL | ControlFlow::Continue(Err("hello")?) | ^ this `?` produces `Result`, which is incompatible with `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = help: the trait `FromResidual` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: for that trait implementation, expected `ControlFlow`, found `Result` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:37:12 @@ -84,7 +85,8 @@ LL | Some(3)?; | ^ this `?` produces `Option`, which is incompatible with `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = help: the trait `FromResidual` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: for that trait implementation, expected `ControlFlow`, found `Option` error[E0277]: the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s (with the same Break type) --> $DIR/bad-interconversion.rs:43:29 @@ -96,7 +98,8 @@ LL | ControlFlow::Break(4_u8)?; | = help: the trait `FromResidual>` is not implemented for `ControlFlow` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` - = help: the trait `FromResidual` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: for that trait implementation, expected `i64`, found `u8` error: aborting due to 8 previous errors diff --git a/tests/ui/tuple/tuple-struct-fields/test2.stderr b/tests/ui/tuple/tuple-struct-fields/test2.stderr index 64a9ac13566f7..784411aba8f8a 100644 --- a/tests/ui/tuple/tuple-struct-fields/test2.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test2.stderr @@ -22,6 +22,8 @@ error[E0412]: cannot find type `foo` in this scope | LL | define_struct! { (foo) } | ^^^ not found in this scope + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/tuple/tuple-struct-fields/test3.stderr b/tests/ui/tuple/tuple-struct-fields/test3.stderr index 75262ed5780e0..00b07c0315292 100644 --- a/tests/ui/tuple/tuple-struct-fields/test3.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test3.stderr @@ -22,6 +22,8 @@ error[E0412]: cannot find type `foo` in this scope | LL | define_struct! { foo } | ^^^ not found in this scope + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr index d8569ebf6b6e2..1fbf180c673f0 100644 --- a/tests/ui/tuple/wrong_argument_ice-4.stderr +++ b/tests/ui/tuple/wrong_argument_ice-4.stderr @@ -8,7 +8,7 @@ LL | | let b = 1; LL | | }); | | - | | | - | |_____unexpected argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` + | |_____unexpected argument of type `{closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15}` | help: remove the extra argument | note: closure defined here diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 0202a2fea496c..359bd09ecd02b 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -36,6 +36,7 @@ note: `V` could also refer to the associated type defined here | LL | type V; | ^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr index ae6462bb62ce5..3484485e3fd7f 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -46,14 +46,17 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/closure_wf_outlives.rs:54:22 | LL | type Opaque = impl Sized; - | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/closure_wf_outlives.rs:59:12 | LL | T: 'static, | ^^^^^^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | type Opaque = impl Sized; | +++++++++ diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs index 9a50c0f988a56..31fea42fa5d8a 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -1,5 +1,5 @@ // compile-flags: --edition=2021 -// check-pass +// build-pass #![feature(type_alias_impl_trait)] fn main() { diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs new file mode 100644 index 0000000000000..7c2d68cceb8fc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs @@ -0,0 +1,19 @@ +// build-pass +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +pub struct Foo { + /// This type must have nontrivial drop glue + field: String, +} + +pub type Tait = impl Sized; + +pub async fn ice_cold(beverage: Tait) { + // Must destructure at least one field of `Foo` + let Foo { field } = beverage; + _ = field; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs new file mode 100644 index 0000000000000..8568b26bea2a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs @@ -0,0 +1,23 @@ +// build-pass +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +fn foo(x: T) { + type Opaque = impl Sized; + let foo: Opaque = (x,); + let (a,): (T,) = foo; +} + +const fn bar(x: T) { + type Opaque = impl Copy; + let foo: Opaque = (x, 2u32); + let (a, b): (T, u32) = foo; +} + +fn main() { + foo::(1); + bar::(1); + const CONST: () = bar::(42u32); + CONST +} 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 8c3a25dbfe7de..c352a33fbbcf0 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 @@ -17,9 +17,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/generic_type_does_not_live_long_enough.rs:13:9 | LL | t - | ^ ...so that the type `T` will meet its required lifetime bounds + | ^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn wrong_generic(t: T) -> WrongGeneric { | +++++++++ diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr index 399775641f8a3..d6dd20739b7af 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -22,9 +22,12 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check3.rs:29:41 | LL | fn test() where Ty: 'static { assert_static::() } - | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test() where Ty: 'static { assert_static::() } | +++++++++ diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index 47bc31e78c34f..81bc64bc32c63 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check4_static.rs:4:18 | LL | type Ty = impl Sized + 'static; - | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | type Ty = impl Sized + 'static; | +++++++++ diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs index baa22e1ce1806..f6cbbf04d8264 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs @@ -1,6 +1,6 @@ // edition: 2021 // build-fail -//~^^ ERROR overflow evaluating the requirement `<() as Recur>::Recur == _` +//~^^ ERROR cycle detected when computing layout of #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr index 0238694c24d3c..2063becdb0838 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr @@ -1,5 +1,19 @@ -error[E0275]: overflow evaluating the requirement `<() as Recur>::Recur == _` +error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}` + | + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... + = note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}`... + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<<() as Recur>::Recur>`... + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... + = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}`, completing the cycle +note: cycle used when elaborating drops for `::recur` + --> $DIR/indirect-recursion-issue-112047.rs:22:5 + | +LL | fn recur(self) -> Self::Recur { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr index a4f6359b904c6..a868562479e8b 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.stderr +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -23,7 +23,7 @@ LL | || -> Closure { || () } | ^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-63279.rs:7:21: 7:23]` + found closure `{closure@$DIR/issue-63279.rs:7:21: 7:23}` help: use parentheses to call this closure | LL | || -> Closure { (|| ())() } @@ -36,7 +36,7 @@ LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-63279.rs:7:5: 7:18]` + found closure `{closure@$DIR/issue-63279.rs:7:5: 7:18}` help: use parentheses to call this closure | LL | (|| -> Closure { || () })() diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr index 8d7f7a07b60c7..26605cdd2c216 100644 --- a/tests/ui/type-alias-impl-trait/issue-94429.stderr +++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/issue-94429.rs:17:9: 17:16] as Generator>::Yield == ()` +error[E0271]: type mismatch resolving `<{generator@$DIR/issue-94429.rs:17:9: 17:16} as Generator>::Yield == ()` --> $DIR/issue-94429.rs:15:26 | LL | fn run(&mut self) -> Self::Gen { diff --git a/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.rs b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.rs new file mode 100644 index 0000000000000..fec0fdc46fbb6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.rs @@ -0,0 +1,9 @@ +#![feature(type_alias_impl_trait)] + +pub type Tait = impl Iterator; +//~^ ERROR use of undeclared lifetime name `'db` +//~| ERROR cannot find type `Key` in this scope +//~| ERROR unconstrained opaque type +//~| ERROR unconstrained opaque type + +pub fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr new file mode 100644 index 0000000000000..d4aeace4ae707 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr @@ -0,0 +1,47 @@ +error[E0261]: use of undeclared lifetime name `'db` + --> $DIR/nested-impl-trait-in-tait.rs:3:40 + | +LL | pub type Tait = impl Iterator; + | ^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'db` lifetime + | +LL | pub type Tait = impl for<'db> Iterator; + | ++++++++ +help: consider introducing lifetime `'db` here + | +LL | pub type Tait<'db> = impl Iterator; + | +++++ + +error[E0412]: cannot find type `Key` in this scope + --> $DIR/nested-impl-trait-in-tait.rs:3:44 + | +LL | pub type Tait = impl Iterator; + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::local_impl::Key; + | + +error: unconstrained opaque type + --> $DIR/nested-impl-trait-in-tait.rs:3:17 + | +LL | pub type Tait = impl Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Tait` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/nested-impl-trait-in-tait.rs:3:49 + | +LL | pub type Tait = impl Iterator; + | ^^^^^^^^^^^^^ + | + = note: `Tait` must be used in combination with a concrete type within the same module + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0261, E0412. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/normalize-alias-type.rs b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs new file mode 100644 index 0000000000000..7c62002b931be --- /dev/null +++ b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs @@ -0,0 +1,32 @@ +// check-pass +// compile-flags: -Z mir-opt-level=3 +#![feature(type_alias_impl_trait)] +#![crate_type = "lib"] +pub trait Tr { + fn get(&self) -> u32; +} + +impl Tr for (u32,) { + #[inline] + fn get(&self) -> u32 { self.0 } +} + +pub fn tr1() -> impl Tr { + (32,) +} + +pub fn tr2() -> impl Tr { + struct Inner { + x: X, + } + type X = impl Tr; + impl Tr for Inner { + fn get(&self) -> u32 { + self.x.get() + } + } + + Inner { + x: tr1(), + } +} diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs new file mode 100644 index 0000000000000..26d94dbb42a36 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || match foo { + None => (), + Some((a, b)) => (), + }; +} + +fn main(){} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs index 857066c78c902..9796823a72440 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs @@ -4,7 +4,7 @@ // FIXME: this is ruled out for now but should work type Foo = fn() -> impl Send; -//~^ ERROR: `impl Trait` only allowed in function and inherent method return types +//~^ ERROR: `impl Trait` only allowed in function and inherent method argument and return types fn make_foo() -> Foo { || 15 diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr index ff375b2ff863f..e57c59d616578 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/type-alias-impl-trait-fn-type.rs:6:20 | LL | type Foo = fn() -> impl Send; diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index 9e96323ab54bb..7d72c9f811af4 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-in-associated-type.rs:36:23 | +LL | impl<'a, T> Trait<'a, T> for () { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Opaque = impl Sized + 'a; | ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ @@ -12,10 +14,12 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () { error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-in-associated-type.rs:36:23 | +LL | impl<'a, T> Trait<'a, T> for () { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Opaque = impl Sized + 'a; | ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index 753a46e882eda..2858afcd46f04 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -2,14 +2,17 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-nested.rs:55:27 | LL | type InnerOpaque = impl Sized; - | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/wf-nested.rs:12:20 | LL | struct IsStatic(T); | ^^^^^^^ -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | type InnerOpaque = impl Sized; | +++++++++ diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index 9ab6685a7f73f..285e4f18ca30c 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-nested.rs:46:17 | LL | let _ = outer.get(); - | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | fn test() { | +++++++++ diff --git a/tests/ui/type-inference/sort_by_key.stderr b/tests/ui/type-inference/sort_by_key.stderr index de7b4b248996a..81af024b3fb94 100644 --- a/tests/ui/type-inference/sort_by_key.stderr +++ b/tests/ui/type-inference/sort_by_key.stderr @@ -1,9 +1,14 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed --> $DIR/sort_by_key.rs:3:40 | LL | lst.sort_by_key(|&(v, _)| v.iter().sum()); - | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` + | ----------- ^^^ cannot infer type of the type parameter `S` declared on the method `sum` + | | + | type must be known at this point | + = note: cannot satisfy `_: Ord` +note: required by a bound in `slice::::sort_by_key` + --> $SRC_DIR/alloc/src/slice.rs:LL:COL help: consider specifying the generic argument | LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); @@ -11,4 +16,4 @@ LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/subtyping-opaque-type.rs b/tests/ui/type/subtyping-opaque-type.rs new file mode 100644 index 0000000000000..beda232ea8b37 --- /dev/null +++ b/tests/ui/type/subtyping-opaque-type.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: -Zvalidate-mir +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl R> Trait for F { + type Assoc = R; +} + +fn foo() -> impl Trait { + || 42 +} + +fn main() {} diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr index 09c4b2053b27e..7be00341d101e 100644 --- a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec<_>` --> $DIR/cannot_infer_local_or_vec.rs:2:9 | LL | let x = vec![]; - | ^ + | ^ ------ type must be known at this point | help: consider giving `x` an explicit type, where the placeholders `_` are specified | diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.rs b/tests/ui/type/type-check/point-at-inference-issue-116155.rs new file mode 100644 index 0000000000000..1e9942d42e867 --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-issue-116155.rs @@ -0,0 +1,17 @@ +struct S(T); + +impl S { + fn new() -> Self { + loop {} + } + + fn constrain T>(&self, _f: F) {} +} + +fn main() { + let s = S::new(); + let c = || true; + s.constrain(c); + let _: S = s; + //~^ ERROR mismatched types +} diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.stderr b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr new file mode 100644 index 0000000000000..c8c01603cb848 --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference-issue-116155.rs:15:23 + | +LL | s.constrain(c); + | - - this argument has type `{closure@$DIR/point-at-inference-issue-116155.rs:13:13: 13:15}`... + | | + | ... which causes `s` to have type `S` +LL | let _: S = s; + | -------- ^ expected `S`, found `S` + | | + | expected due to this + | + = note: expected struct `S` + found struct `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-error-break-tail.stderr b/tests/ui/type/type-error-break-tail.stderr index 16dc6475c6f9f..9a02bc28752ae 100644 --- a/tests/ui/type/type-error-break-tail.stderr +++ b/tests/ui/type/type-error-break-tail.stderr @@ -2,13 +2,16 @@ error[E0308]: mismatched types --> $DIR/type-error-break-tail.rs:3:20 | LL | fn loop_ending() -> i32 { - | --- expected `i32` because of return type + | --- expected `i32` because of this return type LL | loop { + | ---- this loop is expected to be of type `i32` LL | if false { break; } - | ^^^^^ - | | - | expected `i32`, found `()` - | help: give it a value of the expected type: `break 42` + | ^^^^^ expected `i32`, found `()` + | +help: give it a value of the expected type + | +LL | if false { break 42; } + | ++ error: aborting due to previous error diff --git a/tests/ui/typeck/escaping_bound_vars.rs b/tests/ui/typeck/escaping_bound_vars.rs new file mode 100644 index 0000000000000..1fb063d2c2689 --- /dev/null +++ b/tests/ui/typeck/escaping_bound_vars.rs @@ -0,0 +1,16 @@ +// Test for issues/115517 which is fixed by pull/115486 +// This should not ice +trait Test {} + +trait Elide { + fn call(); +} + +pub fn test() +where + (): Test<{ 1 + (<() as Elide(&())>::call) }>, + //~^ ERROR cannot capture late-bound lifetime in constant +{ +} + +fn main() {} diff --git a/tests/ui/typeck/escaping_bound_vars.stderr b/tests/ui/typeck/escaping_bound_vars.stderr new file mode 100644 index 0000000000000..f7077e52a707f --- /dev/null +++ b/tests/ui/typeck/escaping_bound_vars.stderr @@ -0,0 +1,10 @@ +error: cannot capture late-bound lifetime in constant + --> $DIR/escaping_bound_vars.rs:11:35 + | +LL | (): Test<{ 1 + (<() as Elide(&())>::call) }>, + | -^ + | | + | lifetime defined here + +error: aborting due to previous error + diff --git a/tests/ui/typeck/issue-104513-ice.rs b/tests/ui/typeck/issue-104513-ice.rs index bcac0fa1e70ea..4968d3f51fe80 100644 --- a/tests/ui/typeck/issue-104513-ice.rs +++ b/tests/ui/typeck/issue-104513-ice.rs @@ -1,6 +1,6 @@ struct S; fn f() { let _: S = S; //~ ERROR cannot find trait `Oops` in this scope - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } fn main() {} diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 09187d7863a6b..56c6b33615462 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Oops` in this scope LL | let _: S = S; | ^^^^ not found in this scope -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-104513-ice.rs:3:14 | LL | let _: S = S; diff --git a/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs new file mode 100644 index 0000000000000..c319c63eda267 --- /dev/null +++ b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs @@ -0,0 +1,96 @@ +// Regression test for ICE #116473. +// The ICE occurs when arguments are specified on an enum variant +// (which is illegal) and the variant and its preceding path are +// located at different places such as in different macros or +// different expansions of the same macro (i.e. when the macro +// calls itself recursively) + +enum Enum { VariantA { _v1: T1, _v2: T2 }, VariantB } + +type EnumUnit = Enum<(), ()>; + +// Recursive macro call using a tt metavariable for variant +macro_rules! recursive_tt { + () => (recursive_tt!(VariantB)); + ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types +} + + +// Recursive macro call using an ident metavariable for variant +// (the behaviour is different for tt and ident) +macro_rules! recursive_ident { + () => (recursive_ident!(VariantB)); + ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types +} + + +// Mested macro calls (i.e. one calling another) using a tt +// metavariable for variant +macro_rules! nested1_tt { + () => (nested2_tt!(VariantB)); +} + +macro_rules! nested2_tt { + ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types +} + + +// Mested macro calls using an ident metavariable for variant +// (the behaviour is different for tt and ident) +macro_rules! nested1_ident { + () => (nested2_ident!(VariantB)); +} + +macro_rules! nested2_ident { + ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types +} + + +// Mested macro calls when args are passed as metavariable +// instead of the enum variant +macro_rules! nested1_tt_args_in_first_macro { + () => (nested2_tt_args_in_first_macro!(i32, u32)); +} + +macro_rules! nested2_tt_args_in_first_macro { + ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types + = 5 { true } else { false }); +} + +// Mested macro calls when args are passed as metavariable +// instead of the enum variant +macro_rules! nested1_ident_args_in_first_macro { + () => (nested2_ident_args_in_first_macro!(i32, u32)); +} + +macro_rules! nested2_ident_args_in_first_macro { + ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types + = 5 { true } else { false }); +} + +fn main() { + // Macro cases + recursive_tt!(); + recursive_ident!(); + nested1_tt!(); + nested1_ident!(); + nested1_tt_args_in_first_macro!(); + nested1_ident_args_in_first_macro!(); + + // Regular, non-macro case + if let EnumUnit::VariantB:: {} = 5 { true } else { false }; + //~^ ERROR type arguments are not allowed on this type + //~| ERROR mismatched types +} diff --git a/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr new file mode 100644 index 0000000000000..437800f1181b5 --- /dev/null +++ b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr @@ -0,0 +1,255 @@ +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:51 + | +LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | -------- ^^^ ^^^ type argument not allowed + | | + | not allowed on this type +... +LL | recursive_tt!(); + | --------------- + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); +LL + ($variant:tt) => (if let EnumUnit::::$variant {} = 5 { true } else { false }); + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:30 + | +LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `Enum<(), ()>` +... +LL | recursive_tt!(); + | --------------- in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:54 + | +LL | () => (recursive_ident!(VariantB)); + | -------- not allowed on this type +LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^ ^^^ type argument not allowed +... +LL | recursive_ident!(); + | ------------------ + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); +LL + ($variant:ident) => (if let EnumUnit::::$variant {} = 5 { true } else { false }); + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:33 + | +LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `Enum<(), ()>` +... +LL | recursive_ident!(); + | ------------------ in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:51 + | +LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | -------- ^^^ ^^^ type argument not allowed + | | + | not allowed on this type +... +LL | nested1_tt!(); + | ------------- + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); +LL + ($variant:tt) => (if let EnumUnit::::$variant {} = 5 { true } else { false }); + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:30 + | +LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `Enum<(), ()>` +... +LL | nested1_tt!(); + | ------------- in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:54 + | +LL | () => (nested2_ident!(VariantB)); + | -------- not allowed on this type +... +LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^ ^^^ type argument not allowed +... +LL | nested1_ident!(); + | ---------------- + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); +LL + ($variant:ident) => (if let EnumUnit::::$variant {} = 5 { true } else { false }); + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:33 + | +LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `Enum<(), ()>` +... +LL | nested1_ident!(); + | ---------------- in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:64:58 + | +LL | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | -------- ^^^^^ ^^^^^ type argument not allowed + | | + | not allowed on this type +... +LL | nested1_tt_args_in_first_macro!(); + | --------------------------------- + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} +LL + ($arg1:tt, $arg2:tt) => (if let EnumUnit::<$arg1, $arg2>::VariantB {} + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:64:37 + | +LL | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` +... +LL | = 5 { true } else { false }); + | - this expression has type `{integer}` +... +LL | nested1_tt_args_in_first_macro!(); + | --------------------------------- in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `nested2_tt_args_in_first_macro` which comes from the expansion of the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:64 + | +LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | -------- ^^^^^ ^^^^^ type argument not allowed + | | + | not allowed on this type +... +LL | nested1_ident_args_in_first_macro!(); + | ------------------------------------ + | | + | in this macro invocation + | in this macro invocation + | + = note: enum variants can't have type parameters + = note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to specify type parameters on enum `Enum` + | +LL - ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} +LL + ($arg1:ident, $arg2:ident) => (if let EnumUnit::<$arg1, $arg2>::VariantB {} + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:43 + | +LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` +... +LL | = 5 { true } else { false }); + | - this expression has type `{integer}` +... +LL | nested1_ident_args_in_first_macro!(); + | ------------------------------------ in this macro invocation + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + = note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0109]: type arguments are not allowed on this type + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:93:33 + | +LL | if let EnumUnit::VariantB:: {} = 5 { true } else { false }; + | -------- ^^^ ^^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specify type parameters on enum `Enum` + | +LL - if let EnumUnit::VariantB:: {} = 5 { true } else { false }; +LL + if let EnumUnit::::VariantB {} = 5 { true } else { false }; + | + +error[E0308]: mismatched types + --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:93:12 + | +LL | if let EnumUnit::VariantB:: {} = 5 { true } else { false }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `Enum<(), ()>` + | + = note: expected type `{integer}` + found enum `Enum<(), ()>` + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0109, E0308. +For more information about an error, try `rustc --explain E0109`. diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index b622122f33ea7..d65c4306a5f28 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `TakeWhile<&mut IntoIter, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8` +error[E0271]: expected `TakeWhile<&mut IntoIter, {closure@issue-31173.rs:7:21}>` to be an iterator that yields `&_`, but it yields `u8` --> $DIR/issue-31173.rs:11:10 | LL | .cloned() @@ -21,7 +21,7 @@ LL | | }) note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0599]: the method `collect` exists for struct `Cloned, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied +error[E0599]: the method `collect` exists for struct `Cloned, {closure@issue-31173.rs:7:21}>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:12:10 | LL | let temp: Vec = it @@ -43,10 +43,10 @@ LL | | .collect(); = note: doesn't satisfy `_: Iterator` | = note: the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_` - which is required by `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` - `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` - which is required by `&mut Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` + which is required by `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` + `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` + which is required by `&mut Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr index dc4bc5b5f44bb..6c3302f29c2dc 100644 --- a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr +++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5 | LL | fn ice(x: Box>) { - | - help: try adding a return type: `-> (dyn Iterator + 'static)` + | - help: try adding a return type: `-> (dyn Iterator + 'static)` LL | *x | ^^ expected `()`, found `dyn Iterator` | diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr index 0d72ae118f3aa..c46f4ec1ec301 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5 | LL | async fn hello() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer diff --git a/tests/ui/typeck/issue-91267.stderr b/tests/ui/typeck/issue-91267.stderr index 72acd9c673b63..7e48b251980e8 100644 --- a/tests/ui/typeck/issue-91267.stderr +++ b/tests/ui/typeck/issue-91267.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/issue-91267.rs:4:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | type_ascribe!(0, u8=e>) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u8` diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr index f9a240963997b..7be46ac073ea8 100644 --- a/tests/ui/typeck/return_type_containing_closure.stderr +++ b/tests/ui/typeck/return_type_containing_closure.stderr @@ -5,7 +5,7 @@ LL | vec!['a'].iter().map(|c| c) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map, ...>` | = note: expected unit type `()` - found struct `Map, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>` + found struct `Map, {closure@$DIR/return_type_containing_closure.rs:3:26: 3:29}>` help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr index a3517af877cc7..67ca2b061f9b0 100644 --- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr @@ -21,6 +21,8 @@ LL | trait Trait: Copy {} | ^^^^---------- help: remove these generics | | | expected 0 generic arguments + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/typeck-builtin-bound-type-parameters.rs:8:21 diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 0c5e7e3cecb19..a4325b01f02c4 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -443,7 +443,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^ not allowed in type signatures | -note: however, the inferred type `Map, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named +note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:229:29}>, {closure@typeck_type_placeholder_item.rs:229:49}>` cannot be named --> $DIR/typeck_type_placeholder_item.rs:229:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index 482fd3cb44def..e2d867ff266a4 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -1,8 +1,8 @@ -error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope +error[E0599]: no method named `call` found for closure `{closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29}` in the current scope --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10 | LL | mut_.call((0, )); - | ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` + | ^^^^ method not found in `{closure@unboxed-closures-static-call-wrong-trait.rs:6:26}` error: aborting due to previous error diff --git a/tests/ui/unknown-lint-tool-name.stderr b/tests/ui/unknown-lint-tool-name.stderr index 5f8349ce6c3c4..72731ab1e3db4 100644 --- a/tests/ui/unknown-lint-tool-name.stderr +++ b/tests/ui/unknown-lint-tool-name.stderr @@ -21,6 +21,7 @@ LL | #![deny(foo::bar)] | ^^^ | = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:4:9 @@ -29,6 +30,7 @@ LL | #[allow(foo::bar)] | ^^^ | = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr index 32f8d2f45dc81..f0450aea49a4a 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr @@ -8,11 +8,13 @@ error: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr index 2a2a9811bfb0d..20a36b28dc693 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr @@ -20,6 +20,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unknown lint: `test_unstable_lint` --> $DIR/deny-unstable-lint-inline.rs:4:1 @@ -29,6 +30,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr index dd9ecf02fa6b7..a2deecf1caf5e 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr @@ -8,11 +8,13 @@ warning: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `test_unstable_lint` | = note: the `test_unstable_lint` lint is unstable = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr index 0548cd226d804..12afb2e294a3d 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr @@ -20,6 +20,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `test_unstable_lint` --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 @@ -29,6 +30,7 @@ LL | #![allow(test_unstable_lint)] | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 3 warnings emitted diff --git a/tests/ui/use/use-super-global-path.stderr b/tests/ui/use/use-super-global-path.stderr index 7014a12e9ddd2..00d172f4799ae 100644 --- a/tests/ui/use/use-super-global-path.stderr +++ b/tests/ui/use/use-super-global-path.stderr @@ -9,6 +9,8 @@ error[E0433]: failed to resolve: global paths cannot start with `super` | LL | use ::super::{S, Z}; | ^^^^^ global paths cannot start with `super` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0433]: failed to resolve: global paths cannot start with `super` --> $DIR/use-super-global-path.rs:11:15 diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index 2aec641e71edc..cd6c051feedf5 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -14,6 +14,15 @@ help: consider further restricting type parameter `U` LL | fn foo() where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/wf-fn-where-clause.rs:12:16 + | +LL | fn bar() where Vec:, {} + | ^^^^^^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:16 | @@ -34,15 +43,6 @@ LL | struct Vec { LL | t: T, | - ...if indirection were used here: `Box` -error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/wf-fn-where-clause.rs:12:16 - | -LL | fn bar() where Vec:, {} - | ^^^^^^^^^^^^^ `Copy` cannot be made into an object - | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0277. diff --git a/tests/ui/wf/wf-impl-associated-type-region.stderr b/tests/ui/wf/wf-impl-associated-type-region.stderr index b9d4857a3efde..e6fb81247ad66 100644 --- a/tests/ui/wf/wf-impl-associated-type-region.stderr +++ b/tests/ui/wf/wf-impl-associated-type-region.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-impl-associated-type-region.rs:10:16 | +LL | impl<'a, T> Foo<'a> for T { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Bar = &'a T; | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Foo<'a> for T { | ++++ diff --git a/tests/ui/wf/wf-in-fn-type-static.stderr b/tests/ui/wf/wf-in-fn-type-static.stderr index 73fbb9ca670b0..45ad9fba0ce73 100644 --- a/tests/ui/wf/wf-in-fn-type-static.stderr +++ b/tests/ui/wf/wf-in-fn-type-static.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:13:8 | LL | x: fn() -> &'static T - | ^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | ^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | struct Foo { | +++++++++ @@ -13,9 +16,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:18:8 | LL | x: fn(&'static T) - | ^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | ^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | struct Bar { | +++++++++ diff --git a/tests/ui/wf/wf-in-obj-type-static.stderr b/tests/ui/wf/wf-in-obj-type-static.stderr index c3ad42dd5d5ac..4b9b189164c6d 100644 --- a/tests/ui/wf/wf-in-obj-type-static.stderr +++ b/tests/ui/wf/wf-in-obj-type-static.stderr @@ -2,9 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-obj-type-static.rs:14:8 | LL | x: dyn Object<&'static T> - | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | struct Foo { | +++++++++ diff --git a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr index 4d4d8b2ab4d46..e0cf42fd10c89 100644 --- a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr +++ b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -1,10 +1,12 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16 | +LL | impl<'a, T> Trait<'a, T> for usize { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Out = &'a fn(T); | ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for usize { | ++++ @@ -12,10 +14,12 @@ LL | impl<'a, T: 'a> Trait<'a, T> for usize { error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16 | +LL | impl<'a, T> Trait<'a, T> for u32 { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... LL | type Out = &'a dyn Baz; | ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at | -help: consider adding an explicit lifetime bound... +help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for u32 { | ++++ diff --git a/tests/ui/wf/wf-trait-associated-type-region.stderr b/tests/ui/wf/wf-trait-associated-type-region.stderr index 6e2cc8aba4b72..ca7aeb55b250c 100644 --- a/tests/ui/wf/wf-trait-associated-type-region.stderr +++ b/tests/ui/wf/wf-trait-associated-type-region.stderr @@ -1,11 +1,16 @@ error[E0309]: the associated type `>::Type1` may not live long enough --> $DIR/wf-trait-associated-type-region.rs:9:18 | +LL | trait SomeTrait<'a> { + | -- the associated type `>::Type1` must be valid for the lifetime `'a` as defined here... +LL | type Type1; LL | type Type2 = &'a Self::Type1; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ ...so that the reference type `&'a >::Type1` does not outlive the data it points at | - = help: consider adding an explicit lifetime bound `>::Type1: 'a`... - = note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at +help: consider adding an explicit lifetime bound + | +LL | type Type2 = &'a Self::Type1 where >::Type1: 'a; + | ++++++++++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/triagebot.toml b/triagebot.toml index 4a84f3caa95d2..4b051db0d73f2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -542,6 +542,10 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] message = "This PR changes Stable MIR" cc = ["@oli-obk", "@celinval", "@spastorino"] +[mentions."compiler/stable_mir"] +message = "This PR changes Stable MIR" +cc = ["@oli-obk", "@celinval", "@spastorino"] + [mentions."compiler/rustc_target/src/spec"] message = """ These commits modify **compiler targets**. @@ -566,6 +570,11 @@ message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." cc = ["@davidtwco", "@wesleywiser"] +[mentions."src/bootstrap/config.rs"] +message = "This PR changes `src/bootstrap/config.rs`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`." +[mentions."config.example.toml"] +message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`." + [mentions."src/bootstrap/defaults/config.compiler.toml"] message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync." [mentions."src/bootstrap/defaults/config.codegen.toml"] @@ -585,7 +594,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jackh726"] +users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin"] [assign.adhoc_groups] compiler-team = [ @@ -598,7 +607,6 @@ compiler-team = [ compiler-team-contributors = [ "@compiler-errors", "@jackh726", - "@TaKO8Ki", "@WaffleLapkin", "@b-naber", ] @@ -645,7 +653,6 @@ diagnostics = [ "@compiler-errors", "@davidtwco", "@oli-obk", - "@TaKO8Ki", ] parser = [ "@compiler-errors", diff --git a/x b/x index d967988e1c44b..ef3eb8b04b4bf 100755 --- a/x +++ b/x @@ -8,7 +8,7 @@ set -eu # syntax check -sh -n $0 +sh -n "$0" realpath() { if [ -d "$1" ]; then